From c286f92919836dc289605b81a1fd1798ab78ddce Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Thu, 29 Aug 2024 15:23:35 -0400 Subject: [PATCH 01/32] initial module creation --- x-pack/metricbeat/include/list.go | 2 + x-pack/metricbeat/metricbeat.reference.yml | 8 +++ .../metricbeat/module/panos/_meta/config.yml | 6 +++ .../module/panos/_meta/docs.asciidoc | 2 + .../metricbeat/module/panos/_meta/fields.yml | 10 ++++ x-pack/metricbeat/module/panos/doc.go | 2 + x-pack/metricbeat/module/panos/fields.go | 23 ++++++++ .../module/panos/licenses/_meta/data.json | 19 +++++++ .../module/panos/licenses/_meta/docs.asciidoc | 1 + .../module/panos/licenses/_meta/fields.yml | 10 ++++ .../module/panos/licenses/licenses.go | 54 +++++++++++++++++++ .../metricbeat/modules.d/panos.yml.disabled | 9 ++++ 12 files changed, 146 insertions(+) create mode 100644 x-pack/metricbeat/module/panos/_meta/config.yml create mode 100644 x-pack/metricbeat/module/panos/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/doc.go create mode 100644 x-pack/metricbeat/module/panos/fields.go create mode 100644 x-pack/metricbeat/module/panos/licenses/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/licenses/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/licenses/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/licenses/licenses.go create mode 100644 x-pack/metricbeat/modules.d/panos.yml.disabled diff --git a/x-pack/metricbeat/include/list.go b/x-pack/metricbeat/include/list.go index 492e4e7d4d0..13ca19e6ca8 100644 --- a/x-pack/metricbeat/include/list.go +++ b/x-pack/metricbeat/include/list.go @@ -55,6 +55,8 @@ import ( _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/performance" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/sysmetric" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/tablespace" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/licenses" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/collector" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/remote_write" diff --git a/x-pack/metricbeat/metricbeat.reference.yml b/x-pack/metricbeat/metricbeat.reference.yml index ce703584877..7ba66745ac7 100644 --- a/x-pack/metricbeat/metricbeat.reference.yml +++ b/x-pack/metricbeat/metricbeat.reference.yml @@ -1268,6 +1268,14 @@ metricbeat.modules: # username: "" # password: "" +#-------------------------------- Panos Module -------------------------------- +- module: panos + metricsets: ["licenses"] + enabled: false + period: 10s + hosts: ["localhost"] + + #------------------------------- PHP_FPM Module ------------------------------- - module: php_fpm metricsets: diff --git a/x-pack/metricbeat/module/panos/_meta/config.yml b/x-pack/metricbeat/module/panos/_meta/config.yml new file mode 100644 index 00000000000..70cc179e254 --- /dev/null +++ b/x-pack/metricbeat/module/panos/_meta/config.yml @@ -0,0 +1,6 @@ +- module: panos + metricsets: ["licenses"] + enabled: false + period: 10s + hosts: ["localhost"] + diff --git a/x-pack/metricbeat/module/panos/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/_meta/docs.asciidoc new file mode 100644 index 00000000000..342d8c6c6df --- /dev/null +++ b/x-pack/metricbeat/module/panos/_meta/docs.asciidoc @@ -0,0 +1,2 @@ +This is the panos module. + diff --git a/x-pack/metricbeat/module/panos/_meta/fields.yml b/x-pack/metricbeat/module/panos/_meta/fields.yml new file mode 100644 index 00000000000..52e2568926b --- /dev/null +++ b/x-pack/metricbeat/module/panos/_meta/fields.yml @@ -0,0 +1,10 @@ +- key: panos + title: "panos" + release: beta + description: > + panos module + fields: + - name: panos + type: group + description: > + fields: diff --git a/x-pack/metricbeat/module/panos/doc.go b/x-pack/metricbeat/module/panos/doc.go new file mode 100644 index 00000000000..10f82619674 --- /dev/null +++ b/x-pack/metricbeat/module/panos/doc.go @@ -0,0 +1,2 @@ +// Package panos is a Metricbeat module that contains MetricSets. +package panos diff --git a/x-pack/metricbeat/module/panos/fields.go b/x-pack/metricbeat/module/panos/fields.go new file mode 100644 index 00000000000..15abde89a68 --- /dev/null +++ b/x-pack/metricbeat/module/panos/fields.go @@ -0,0 +1,23 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +// Code generated by beats/dev-tools/cmd/asset/asset.go - DO NOT EDIT. + +package panos + +import ( + "github.com/elastic/beats/v7/libbeat/asset" +) + +func init() { + if err := asset.SetFields("metricbeat", "panos", asset.ModuleFieldsPri, AssetPanos); err != nil { + panic(err) + } +} + +// AssetPanos returns asset data. +// This is the base64 encoded zlib format compressed contents of module/panos. +func AssetPanos() string { + return "eJx8j00OwiAYRPecYtJ9L8DCnQfBMhpSCoSPRnt70+JPbYhvBxPeDD1GLhrJhCgKKK54anTbuVNApqcRalxYjAIsZcguFReDxkkBqG8xRTt7KuDq6K3oLeoRzMSvfqUsiRq3HOf0umk4fzV7lXcDg1A+Qcu4clz+ptlWabiPM/ZT+DBT2v68p64ZudxjtofsT/fKuQprqXoGAAD//0kFbSc=" +} diff --git a/x-pack/metricbeat/module/panos/licenses/_meta/data.json b/x-pack/metricbeat/module/panos/licenses/_meta/data.json new file mode 100644 index 00000000000..eb1336ea518 --- /dev/null +++ b/x-pack/metricbeat/module/panos/licenses/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"licenses", + "rtt":44269 + }, + "panos":{ + "licenses":{ + "example": "licenses" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/licenses/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/licenses/_meta/docs.asciidoc new file mode 100644 index 00000000000..dcf92265866 --- /dev/null +++ b/x-pack/metricbeat/module/panos/licenses/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the licenses metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml b/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml new file mode 100644 index 00000000000..9c8b9547ae7 --- /dev/null +++ b/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: licenses + type: group + release: beta + description: > + licenses + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/licenses/licenses.go b/x-pack/metricbeat/module/panos/licenses/licenses.go new file mode 100644 index 00000000000..221b4fee534 --- /dev/null +++ b/x-pack/metricbeat/module/panos/licenses/licenses.go @@ -0,0 +1,54 @@ +package licenses + +import ( + "github.com/elastic/elastic-agent-libs/mapstr" + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet("panos", "licenses", New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + counter int +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos licenses metricset is beta.") + + config := struct{}{} + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + + return &MetricSet{ + BaseMetricSet: base, + counter: 1, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + report.Event(mb.Event{ + MetricSetFields: mapstr.M{ + "counter": m.counter, + }, + }) + m.counter++ + + return nil +} diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panos.yml.disabled new file mode 100644 index 00000000000..9ad01318984 --- /dev/null +++ b/x-pack/metricbeat/modules.d/panos.yml.disabled @@ -0,0 +1,9 @@ +# Module: panos +# Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html + +- module: panos + metricsets: ["licenses"] + enabled: false + period: 10s + hosts: ["localhost"] + From 741fc30aed28b107b83cfb6fa9d1e68f25709382 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sat, 31 Aug 2024 15:23:31 -0400 Subject: [PATCH 02/32] panos.system metricset running --- x-pack/metricbeat/include/list.go | 1 + x-pack/metricbeat/module/panos/fields.go | 2 +- .../module/panos/licenses/licenses.go | 111 ++++++- .../module/panos/system/_meta/data.json | 19 ++ .../module/panos/system/_meta/docs.asciidoc | 1 + .../module/panos/system/_meta/fields.yml | 10 + .../metricbeat/module/panos/system/system.go | 313 ++++++++++++++++++ x-pack/metricbeat/module/panos/types.go | 28 ++ x-pack/metricbeat/modules.d/panos.yml | 12 + .../metricbeat/modules.d/panos.yml.disabled | 9 - 10 files changed, 484 insertions(+), 22 deletions(-) create mode 100644 x-pack/metricbeat/module/panos/system/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/system/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/system/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/system/system.go create mode 100644 x-pack/metricbeat/module/panos/types.go create mode 100644 x-pack/metricbeat/modules.d/panos.yml delete mode 100644 x-pack/metricbeat/modules.d/panos.yml.disabled diff --git a/x-pack/metricbeat/include/list.go b/x-pack/metricbeat/include/list.go index 13ca19e6ca8..98930a4fc91 100644 --- a/x-pack/metricbeat/include/list.go +++ b/x-pack/metricbeat/include/list.go @@ -57,6 +57,7 @@ import ( _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/tablespace" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/licenses" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/system" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/collector" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/remote_write" diff --git a/x-pack/metricbeat/module/panos/fields.go b/x-pack/metricbeat/module/panos/fields.go index 15abde89a68..44ca9ac7538 100644 --- a/x-pack/metricbeat/module/panos/fields.go +++ b/x-pack/metricbeat/module/panos/fields.go @@ -19,5 +19,5 @@ func init() { // AssetPanos returns asset data. // This is the base64 encoded zlib format compressed contents of module/panos. func AssetPanos() string { - return "eJx8j00OwiAYRPecYtJ9L8DCnQfBMhpSCoSPRnt70+JPbYhvBxPeDD1GLhrJhCgKKK54anTbuVNApqcRalxYjAIsZcguFReDxkkBqG8xRTt7KuDq6K3oLeoRzMSvfqUsiRq3HOf0umk4fzV7lXcDg1A+Qcu4clz+ptlWabiPM/ZT+DBT2v68p64ZudxjtofsT/fKuQprqXoGAAD//0kFbSc=" + return "eJzEj0tOgDAYhPc9xYQ9F+jCnQepdDQNfaV/ifb2BuoDoXFn/Hbwp9/MzFjZNLKJSRRQXfXUmI7vSQGFnkao8cRqFGApS3G5uhQ1HhSA/hYh2c1TAc+O3oo+TjOiCfzW79SWqfFS0pY//gycPzVnlXcLo1C+DiPjzrX5J8O0zsB9rXGuwjcT8rH5TG+zsr2mYi+3X7J3Hruwh96WS5PK8Be7b+Z/XP0eAAD//wwMqSs=" } diff --git a/x-pack/metricbeat/module/panos/licenses/licenses.go b/x-pack/metricbeat/module/panos/licenses/licenses.go index 221b4fee534..f79210ffa96 100644 --- a/x-pack/metricbeat/module/panos/licenses/licenses.go +++ b/x-pack/metricbeat/module/panos/licenses/licenses.go @@ -1,9 +1,45 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package licenses import ( - "github.com/elastic/elastic-agent-libs/mapstr" + "encoding/xml" + "time" + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Licenses []License `xml:"licenses>entry"` +} + +type License struct { + Feature string `xml:"feature"` + Description string `xml:"description"` + Serial string `xml:"serial"` + Issued string `xml:"issued"` + Expires string `xml:"expires"` + Expired string `xml:"expired"` + AuthCode string `xml:"authcode"` +} + +const ( + metricsetName = "licenses" + vsys = "shared" + query = "" ) // init registers the MetricSet with the central registry as soon as the program @@ -11,7 +47,7 @@ import ( // the MetricSet for each host is defined in the module's configuration. After the // MetricSet has been created then Fetch will begin to be called periodically. func init() { - mb.Registry.MustAddMetricSet("panos", "licenses", New) + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) } // MetricSet holds any configuration or state information. It must implement @@ -20,7 +56,9 @@ func init() { // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - counter int + config panos.Config + logger *logp.Logger + client *pango.Firewall } // New creates a new instance of the MetricSet. New is responsible for unpacking @@ -28,27 +66,76 @@ type MetricSet struct { func New(base mb.BaseMetricSet) (mb.MetricSet, error) { cfgwarn.Beta("The panos licenses metricset is beta.") - config := struct{}{} + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + if err := base.Module().UnpackConfig(&config); err != nil { return nil, err } + logger.Debugf("panos_licenses metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} return &MetricSet{ BaseMetricSet: base, - counter: 1, + config: config, + logger: logger, + client: client, }, nil } // Fetch method implements the data gathering and data conversion to the right // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - report.Event(mb.Event{ - MetricSetFields: mapstr.M{ - "counter": m.counter, - }, - }) - m.counter++ +func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Fatalf("Failed to initialize client: %s", err) + } + log.Infof("panos_licenses.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Fatalf("Error: %s", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Fatalf("Error: %s", err) + } + + events := getEvents(m, response.Result.Licenses) + + for _, event := range events { + reporter.Event(event) + } return nil } + +func getEvents(m *MetricSet, licenses []License) []mb.Event { + events := make([]mb.Event, 0, len(licenses)) + + currentTime := time.Now() + + for _, license := range licenses { + event := mb.Event{MetricSetFields: mapstr.M{ + "license.feature": license.Feature, + "license.description": license.Description, + "license.serial": license.Serial, + "license.issued": license.Issued, + "license.expires": license.Expires, + "license.expired": license.Expired, + "license.auth_code": license.AuthCode, + "observer.ip": m.config.HostIp, + }} + event.Timestamp = currentTime + events = append(events, event) + } + + return events + +} diff --git a/x-pack/metricbeat/module/panos/system/_meta/data.json b/x-pack/metricbeat/module/panos/system/_meta/data.json new file mode 100644 index 00000000000..931eba1a52a --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"system", + "rtt":44269 + }, + "panos":{ + "system":{ + "example": "system" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/system/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/system/_meta/docs.asciidoc new file mode 100644 index 00000000000..59ea987088d --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the system metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/system/_meta/fields.yml b/x-pack/metricbeat/module/panos/system/_meta/fields.yml new file mode 100644 index 00000000000..9dc174c52d2 --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: system + type: group + release: beta + description: > + system + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/system/system.go b/x-pack/metricbeat/module/panos/system/system.go new file mode 100644 index 00000000000..9efdfa75f19 --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/system.go @@ -0,0 +1,313 @@ +package system + +import ( + "encoding/xml" + "fmt" + "regexp" + "strings" + "time" + + "github.com/PaloAltoNetworks/pango" + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +type Response struct { + Status string `xml:"status,attr"` + Result string `xml:"result"` +} + +type SystemLoad struct { + one_minute float64 + five_minute float64 + fifteen_minute float64 +} + +type Uptime struct { + Days int + Hours string +} + +type SystemInfo struct { + Uptime Uptime + UserCount int + LoadAverage SystemLoad +} + +type TaskInfo struct { + Total int + Running int + Sleeping int + Stopped int + Zombie int +} + +type CPUInfo struct { + User float64 + System float64 + Nice float64 + Idle float64 + Wait float64 + Hi float64 + SystemInt float64 + Steal float64 +} + +type MemoryInfo struct { + Total float64 + Free float64 + Used float64 + BufferCache float64 +} + +type SwapInfo struct { + Total float64 + Free float64 + Used float64 + Available float64 +} + +const ( + metricsetName = "system" + vsys = "shared" + query = "" +) + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos licenses metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_licenses metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Infof("panos_licenses.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + event := getEvent(m, response.Result) + reporter.Event(event) + + return nil +} + +func getEvent(m *MetricSet, input string) mb.Event { + currentTime := time.Now() + + // The output is standard "top" output, and we only need the top 5 lines + lines := strings.Split(input, "\n") + lines = lines[:5] + + systemInfo := parseSystemInfo(lines[0]) + taskInfo := parseTaskInfo(lines[1]) + cpuInfo := parseCPUInfo(lines[2]) + memoryInfo := parseMemoryInfo(lines[3]) + swapInfo := parseSwapInfo(lines[4]) + + event := mb.Event{MetricSetFields: mapstr.M{ + "system.uptime.days": systemInfo.Uptime.Days, + "system.uptime.hours": systemInfo.Uptime.Hours, + "system.user_count": systemInfo.UserCount, + "system.load_average.1m": systemInfo.LoadAverage.one_minute, + "system.load_average.5m": systemInfo.LoadAverage.five_minute, + "system.load_average.15m": systemInfo.LoadAverage.fifteen_minute, + "system.tasks.total": taskInfo.Total, + "system.tasks.running": taskInfo.Running, + "system.tasks.sleeping": taskInfo.Sleeping, + "system.tasks.stopped": taskInfo.Stopped, + "system.tasks.zombie": taskInfo.Zombie, + "system.cpu.user": cpuInfo.User, + "system.cpu.system": cpuInfo.System, + "system.cpu.nice": cpuInfo.Nice, + "system.cpu.idle": cpuInfo.Idle, + "system.cpu.wait": cpuInfo.Wait, + "system.cpu.hi": cpuInfo.Hi, + "system.cpu.system_int": cpuInfo.SystemInt, + "system.cpu.steal": cpuInfo.Steal, + "system.memory.total": memoryInfo.Total, + "system.memory.free": memoryInfo.Free, + "system.memory.used": memoryInfo.Used, + "system.memory.buffer_cache": memoryInfo.BufferCache, + "system.swap.total": swapInfo.Total, + "system.swap.free": swapInfo.Free, + "system.swap.used": swapInfo.Used, + "system.swap.available": swapInfo.Available, + "observer.ip": m.config.HostIp, + }} + event.Timestamp = currentTime + + return event +} + +func parseSystemInfo(line string) SystemInfo { + // top - 07:51:37 up 108 days, 1:38, 0 users, load average: 5.52, 5.79, 5.99 + re := regexp.MustCompile(`\s+`) + normal := re.ReplaceAllString(line, " ") + fields := strings.Split(normal, " ") + + uptime := Uptime{parseInt(fields[4]), fields[6]} + loadAverage := strings.Split(normal, ": ")[1] + loadAverageValues := strings.Split(loadAverage, ", ") + + users := fields[7] + var loadAverageFloat []float64 + for _, value := range loadAverageValues { + loadAverageFloat = append(loadAverageFloat, parseFloat(value)) + } + + SystemLoad := SystemLoad{loadAverageFloat[0], loadAverageFloat[1], loadAverageFloat[2]} + return SystemInfo{ + Uptime: uptime, + UserCount: parseInt(users), + LoadAverage: SystemLoad, + } +} + +func parseTaskInfo(line string) TaskInfo { + //Tasks: 189 total, 7 running, 182 sleeping, 0 stopped, 0 zombie + values := strings.Fields(line) + + total := parseInt(values[1]) + running := parseInt(values[3]) + sleeping := parseInt(values[5]) + stopped := parseInt(values[7]) + zombie := parseInt(values[9]) + + return TaskInfo{ + Total: total, + Running: running, + Sleeping: sleeping, + Stopped: stopped, + Zombie: zombie, + } +} + +func parseCPUInfo(line string) CPUInfo { + //%Cpu(s): 73.0 us, 4.6 sy, 0.0 ni, 21.7 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st + values := strings.Fields(line) + + user := parseFloat(values[1]) + system := parseFloat(values[3]) + nice := parseFloat(values[5]) + idle := parseFloat(values[7]) + wait := parseFloat(values[9]) + hi := parseFloat(values[11]) + systemInt := parseFloat(values[13]) + steal := parseFloat(values[15]) + + return CPUInfo{ + User: user, + System: system, + Nice: nice, + Idle: idle, + Wait: wait, + Hi: hi, + SystemInt: systemInt, + Steal: steal, + } +} + +func parseMemoryInfo(line string) MemoryInfo { + //MiB Mem : 5026.9 total, 414.2 free, 2541.5 used, 2071.1 buff/cache + values := strings.Fields(line) + + total := parseFloat(values[3]) + free := parseFloat(values[5]) + used := parseFloat(values[7]) + bufferCache := parseFloat(values[9]) + + return MemoryInfo{ + Total: total, + Free: free, + Used: used, + BufferCache: bufferCache, + } +} + +func parseSwapInfo(line string) SwapInfo { + //MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem + values := strings.Fields(line) + + total := parseFloat(values[2]) + free := parseFloat(values[4]) + used := parseFloat(values[6]) + available := parseFloat(values[8]) + + return SwapInfo{ + Total: total, + Free: free, + Used: used, + Available: available, + } +} + +func parseFloat(value string) float64 { + var result float64 + fmt.Sscanf(value, "%f", &result) + return result +} + +func parseInt(value string) int { + var result int + fmt.Sscanf(value, "%d", &result) + return result +} diff --git a/x-pack/metricbeat/module/panos/types.go b/x-pack/metricbeat/module/panos/types.go new file mode 100644 index 00000000000..d0024476b62 --- /dev/null +++ b/x-pack/metricbeat/module/panos/types.go @@ -0,0 +1,28 @@ +package panos + +import ( + "github.com/PaloAltoNetworks/pango" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/logp" +) + +const ( + ModuleName = "panos" +) + +type Config struct { + HostIp string `config:"host_ip"` + ApiKey string `config:"apiKey"` + DebugMode string `config:"apiDebugMode"` +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + Config Config + Logger *logp.Logger + Client *pango.Firewall +} diff --git a/x-pack/metricbeat/modules.d/panos.yml b/x-pack/metricbeat/modules.d/panos.yml new file mode 100644 index 00000000000..2762873068b --- /dev/null +++ b/x-pack/metricbeat/modules.d/panos.yml @@ -0,0 +1,12 @@ +# Module: panos +# Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html + +- module: panos + metricsets: ["licenses", "system"] + enabled: true + period: 10s + host_ip: "10.200.99.13" + apiKey: "LUFRPT1VNFV2eXUvbUJTNUNaT2VwOHMxd0ViRG1VZDQ9NURkZDcvZ3kwYTZWbENJeVZlcFdUSDQ2NDBOVFpoRjJWck9Ic0R5YVRsMFdzRVhVRzlmUHdoUGdGckt1bFVlTw==" + apiDebugMode: false + + diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panos.yml.disabled deleted file mode 100644 index 9ad01318984..00000000000 --- a/x-pack/metricbeat/modules.d/panos.yml.disabled +++ /dev/null @@ -1,9 +0,0 @@ -# Module: panos -# Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html - -- module: panos - metricsets: ["licenses"] - enabled: false - period: 10s - hosts: ["localhost"] - From b4140e2ea9357bda1a726d378ae3a8d2f74d8414 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sat, 31 Aug 2024 15:40:52 -0400 Subject: [PATCH 03/32] remove testing data --- x-pack/metricbeat/modules.d/panos.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/metricbeat/modules.d/panos.yml b/x-pack/metricbeat/modules.d/panos.yml index 2762873068b..19658f884a9 100644 --- a/x-pack/metricbeat/modules.d/panos.yml +++ b/x-pack/metricbeat/modules.d/panos.yml @@ -5,8 +5,8 @@ metricsets: ["licenses", "system"] enabled: true period: 10s - host_ip: "10.200.99.13" - apiKey: "LUFRPT1VNFV2eXUvbUJTNUNaT2VwOHMxd0ViRG1VZDQ9NURkZDcvZ3kwYTZWbENJeVZlcFdUSDQ2NDBOVFpoRjJWck9Ic0R5YVRsMFdzRVhVRzlmUHdoUGdGckt1bFVlTw==" + host_ip: "999.999.999.999" + apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" apiDebugMode: false From f78742f1c55714a44bc3ee34d6961307ad61eb00 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sat, 31 Aug 2024 18:23:12 -0400 Subject: [PATCH 04/32] panos.disk metricset working --- x-pack/metricbeat/include/list.go | 1 + .../module/panos/disk/_meta/data.json | 19 +++ .../module/panos/disk/_meta/docs.asciidoc | 1 + .../module/panos/disk/_meta/fields.yml | 10 ++ x-pack/metricbeat/module/panos/disk/disk.go | 161 ++++++++++++++++++ x-pack/metricbeat/module/panos/fields.go | 2 +- x-pack/metricbeat/modules.d/panos.yml | 12 -- .../metricbeat/modules.d/panos.yml.disabled | 9 + 8 files changed, 202 insertions(+), 13 deletions(-) create mode 100644 x-pack/metricbeat/module/panos/disk/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/disk/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/disk/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/disk/disk.go delete mode 100644 x-pack/metricbeat/modules.d/panos.yml create mode 100644 x-pack/metricbeat/modules.d/panos.yml.disabled diff --git a/x-pack/metricbeat/include/list.go b/x-pack/metricbeat/include/list.go index 98930a4fc91..da95af6d808 100644 --- a/x-pack/metricbeat/include/list.go +++ b/x-pack/metricbeat/include/list.go @@ -56,6 +56,7 @@ import ( _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/sysmetric" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/tablespace" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/disk" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/licenses" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/system" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus" diff --git a/x-pack/metricbeat/module/panos/disk/_meta/data.json b/x-pack/metricbeat/module/panos/disk/_meta/data.json new file mode 100644 index 00000000000..4a2dd91461f --- /dev/null +++ b/x-pack/metricbeat/module/panos/disk/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"disk", + "rtt":44269 + }, + "panos":{ + "disk":{ + "example": "disk" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/disk/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/disk/_meta/docs.asciidoc new file mode 100644 index 00000000000..163ebb7e0f1 --- /dev/null +++ b/x-pack/metricbeat/module/panos/disk/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the disk metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/disk/_meta/fields.yml b/x-pack/metricbeat/module/panos/disk/_meta/fields.yml new file mode 100644 index 00000000000..8993a245d31 --- /dev/null +++ b/x-pack/metricbeat/module/panos/disk/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: disk + type: group + release: beta + description: > + disk + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/disk/disk.go b/x-pack/metricbeat/module/panos/disk/disk.go new file mode 100644 index 00000000000..e3707389dc2 --- /dev/null +++ b/x-pack/metricbeat/module/panos/disk/disk.go @@ -0,0 +1,161 @@ +package disk + +import ( + "encoding/xml" + "strings" + "time" + + "github.com/PaloAltoNetworks/pango" + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +type Response struct { + XMLName xml.Name `xml:"response"` + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Data string `xml:",cdata"` +} + +type Filesystem struct { + Name string + Size string + Used string + Avail string + UsePerc string + Mounted string +} + +const ( + metricsetName = "disk" + vsys = "shared" + query = "" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet("panos", "disk", New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos licenses metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_licenses metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Infof("panos_licenses.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + filesystems := getFilesystems(response.Result.Data) + events := getEvents(m, filesystems) + + for _, event := range events { + reporter.Event(event) + } + return nil +} + +func getFilesystems(input string) []Filesystem { + lines := strings.Split(input, "\n") + filesystems := make([]Filesystem, 0) + + for _, line := range lines[1:] { + fields := strings.Fields(line) + if len(fields) == 6 { + filesystem := Filesystem{ + Name: fields[0], + Size: fields[1], + Used: fields[2], + Avail: fields[3], + UsePerc: fields[4], + Mounted: fields[5], + } + filesystems = append(filesystems, filesystem) + } + } + return filesystems +} + +func getEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { + events := make([]mb.Event, 0, len(filesystems)) + + currentTime := time.Now() + + for _, filesystem := range filesystems { + event := mb.Event{MetricSetFields: mapstr.M{ + "filesystem.name": filesystem.Name, + "filesystem.size": filesystem.Size, + "filesystem.used": filesystem.Used, + "filesystem.avail": filesystem.Avail, + "filesystem.use_perc": filesystem.UsePerc, + "filesystem.mounted": filesystem.Mounted, + "observer.ip": m.config.HostIp, + }} + event.Timestamp = currentTime + + events = append(events, event) + } + + return events + +} diff --git a/x-pack/metricbeat/module/panos/fields.go b/x-pack/metricbeat/module/panos/fields.go index 44ca9ac7538..ce9f9aecce7 100644 --- a/x-pack/metricbeat/module/panos/fields.go +++ b/x-pack/metricbeat/module/panos/fields.go @@ -19,5 +19,5 @@ func init() { // AssetPanos returns asset data. // This is the base64 encoded zlib format compressed contents of module/panos. func AssetPanos() string { - return "eJzEj0tOgDAYhPc9xYQ9F+jCnQepdDQNfaV/ifb2BuoDoXFn/Hbwp9/MzFjZNLKJSRRQXfXUmI7vSQGFnkao8cRqFGApS3G5uhQ1HhSA/hYh2c1TAc+O3oo+TjOiCfzW79SWqfFS0pY//gycPzVnlXcLo1C+DiPjzrX5J8O0zsB9rXGuwjcT8rH5TG+zsr2mYi+3X7J3Hruwh96WS5PK8Be7b+Z/XP0eAAD//wwMqSs=" + return "eJzMjztOBDEQRHOforT5XsABGQcx6wJZ45/cXoFvj2a8wHwsshFU5m75Vb8rJjaNbGISBVRXPTUuy/uigEJPI9R4YTUKsJRbcbm6FDWeFID+FyHZu6cCXh29Fb2srogm8Ac/p7ZMjbeS7vkxGTC3mDXKOpm+hyPanP3VXxk2PVZb7r5+fQI/TMiL6zr9kontPRW72/3SO+e5A3vpwdi7G6NQzrAesP+RuTSpDGd4H8h/aP0ZAAD///G74zs=" } diff --git a/x-pack/metricbeat/modules.d/panos.yml b/x-pack/metricbeat/modules.d/panos.yml deleted file mode 100644 index 19658f884a9..00000000000 --- a/x-pack/metricbeat/modules.d/panos.yml +++ /dev/null @@ -1,12 +0,0 @@ -# Module: panos -# Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html - -- module: panos - metricsets: ["licenses", "system"] - enabled: true - period: 10s - host_ip: "999.999.999.999" - apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - apiDebugMode: false - - diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panos.yml.disabled new file mode 100644 index 00000000000..9ad01318984 --- /dev/null +++ b/x-pack/metricbeat/modules.d/panos.yml.disabled @@ -0,0 +1,9 @@ +# Module: panos +# Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html + +- module: panos + metricsets: ["licenses"] + enabled: false + period: 10s + hosts: ["localhost"] + From daf2caf12fa2d963bc637641947b923376bf8ad3 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sun, 1 Sep 2024 11:11:53 -0400 Subject: [PATCH 05/32] rename metricset --- .../metricbeat/module/panos/{disk => filesystem}/_meta/data.json | 0 .../module/panos/{disk => filesystem}/_meta/docs.asciidoc | 0 .../metricbeat/module/panos/{disk => filesystem}/_meta/fields.yml | 0 x-pack/metricbeat/module/panos/{disk => filesystem}/disk.go | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename x-pack/metricbeat/module/panos/{disk => filesystem}/_meta/data.json (100%) rename x-pack/metricbeat/module/panos/{disk => filesystem}/_meta/docs.asciidoc (100%) rename x-pack/metricbeat/module/panos/{disk => filesystem}/_meta/fields.yml (100%) rename x-pack/metricbeat/module/panos/{disk => filesystem}/disk.go (100%) diff --git a/x-pack/metricbeat/module/panos/disk/_meta/data.json b/x-pack/metricbeat/module/panos/filesystem/_meta/data.json similarity index 100% rename from x-pack/metricbeat/module/panos/disk/_meta/data.json rename to x-pack/metricbeat/module/panos/filesystem/_meta/data.json diff --git a/x-pack/metricbeat/module/panos/disk/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc similarity index 100% rename from x-pack/metricbeat/module/panos/disk/_meta/docs.asciidoc rename to x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc diff --git a/x-pack/metricbeat/module/panos/disk/_meta/fields.yml b/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml similarity index 100% rename from x-pack/metricbeat/module/panos/disk/_meta/fields.yml rename to x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml diff --git a/x-pack/metricbeat/module/panos/disk/disk.go b/x-pack/metricbeat/module/panos/filesystem/disk.go similarity index 100% rename from x-pack/metricbeat/module/panos/disk/disk.go rename to x-pack/metricbeat/module/panos/filesystem/disk.go From 6004852664a08f774d52de79805f456d8f5ac636 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sun, 1 Sep 2024 11:12:53 -0400 Subject: [PATCH 06/32] change metricset name --- .../metricbeat/module/panos/filesystem/{disk.go => filesystem.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename x-pack/metricbeat/module/panos/filesystem/{disk.go => filesystem.go} (100%) diff --git a/x-pack/metricbeat/module/panos/filesystem/disk.go b/x-pack/metricbeat/module/panos/filesystem/filesystem.go similarity index 100% rename from x-pack/metricbeat/module/panos/filesystem/disk.go rename to x-pack/metricbeat/module/panos/filesystem/filesystem.go From 6ff51e678811684579ef74b2a54ea8824dea7a70 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sun, 1 Sep 2024 13:04:17 -0400 Subject: [PATCH 07/32] bgp_peers metricset working --- x-pack/metricbeat/include/list.go | 3 +- .../module/panos/bgp_peers/_meta/data.json | 19 +++ .../panos/bgp_peers/_meta/docs.asciidoc | 1 + .../module/panos/bgp_peers/_meta/fields.yml | 10 ++ .../module/panos/bgp_peers/bgp_peers.go | 159 ++++++++++++++++++ .../module/panos/bgp_peers/types.go | 79 +++++++++ .../module/panos/filesystem/_meta/data.json | 6 +- .../panos/filesystem/_meta/docs.asciidoc | 2 +- .../module/panos/filesystem/_meta/fields.yml | 4 +- .../module/panos/filesystem/filesystem.go | 22 +-- .../module/panos/licenses/licenses.go | 28 +-- .../metricbeat/module/panos/system/system.go | 4 +- x-pack/metricbeat/module/panos/types.go | 17 -- .../metricbeat/modules.d/panos.yml.disabled | 7 +- 14 files changed, 313 insertions(+), 48 deletions(-) create mode 100644 x-pack/metricbeat/module/panos/bgp_peers/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/bgp_peers/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go create mode 100644 x-pack/metricbeat/module/panos/bgp_peers/types.go diff --git a/x-pack/metricbeat/include/list.go b/x-pack/metricbeat/include/list.go index da95af6d808..5fe8cab6f7a 100644 --- a/x-pack/metricbeat/include/list.go +++ b/x-pack/metricbeat/include/list.go @@ -56,9 +56,10 @@ import ( _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/sysmetric" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/tablespace" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/disk" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/filesystem" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/licenses" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/system" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/bgp_peers" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/collector" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/remote_write" diff --git a/x-pack/metricbeat/module/panos/bgp_peers/_meta/data.json b/x-pack/metricbeat/module/panos/bgp_peers/_meta/data.json new file mode 100644 index 00000000000..aedd8f2eb7f --- /dev/null +++ b/x-pack/metricbeat/module/panos/bgp_peers/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"bgp_peers", + "rtt":44269 + }, + "panos":{ + "bgp_peers":{ + "example": "bgp_peers" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/bgp_peers/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/bgp_peers/_meta/docs.asciidoc new file mode 100644 index 00000000000..369e008b9b3 --- /dev/null +++ b/x-pack/metricbeat/module/panos/bgp_peers/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the bgp_peers metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml b/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml new file mode 100644 index 00000000000..16c4779b58f --- /dev/null +++ b/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: bgp_peers + type: group + release: beta + description: > + bgp_peers + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go b/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go new file mode 100644 index 00000000000..81f78880a9f --- /dev/null +++ b/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go @@ -0,0 +1,159 @@ +package bgp_peers + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "bgp_peers" + vsys = "shared" + query = "default" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos licenses metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_licenses metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Infof("============================= panos/bgp_peers.Fetch initialized client ==============================") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + events := getEvents(m, response.Result.Entries) + + for _, event := range events { + log.Debugf("====================================================") + log.Debugf("Reporting event: %v", event) + log.Debugf("====================================================") + reporter.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, entries []Entry) []mb.Event { + events := make([]mb.Event, 0, len(entries)) + currentTime := time.Now() + log := m.Logger() + + for _, entry := range entries { + log.Debugf("====================================================") + log.Debugf("Processing entry: %v", entry) + log.Debugf("====================================================") + + event := mb.Event{MetricSetFields: mapstr.M{ + "peer_name": entry.Peer, + "virtual_router": entry.Vr, + "peer_group": entry.PeerGroup, + "peer_router_id": entry.PeerRouterID, + "remote_as_asn": entry.RemoteAS, + "status": entry.Status, + "status_duration": entry.StatusDuration, + "password_set": entry.PasswordSet, + "passive": entry.Passive, + "multi_hop_ttl": entry.MultiHopTTL, + "peer_address": entry.PeerAddress, + "local_address": entry.LocalAddress, + "reflector_client": entry.ReflectorClient, + "same_confederation": entry.SameConfederation, + "aggregate_confed_as": entry.AggregateConfedAS, + "peering_type": entry.PeeringType, + "connect_retry_interval": entry.ConnectRetryInterval, + "open_delay": entry.OpenDelay, + "idle_hold": entry.IdleHold, + "prefix_limit": entry.PrefixLimit, + "holdtime": entry.Holdtime, + "holdtime_config": entry.HoldtimeConfig, + "keepalive": entry.Keepalive, + "keepalive_config": entry.KeepaliveConfig, + "msg_update_in": entry.MsgUpdateIn, + "msg_update_out": entry.MsgUpdateOut, + "msg_total_in": entry.MsgTotalIn, + "msg_total_out": entry.MsgTotalOut, + "last_update_age": entry.LastUpdateAge, + "last_error": entry.LastError, + "status_flap_counts": entry.StatusFlapCounts, + "established_counts": entry.EstablishedCounts, + "orf_entry_received": entry.ORFEntryReceived, + "nexthop_self": entry.NexthopSelf, + "nexthop_thirdparty": entry.NexthopThirdparty, + "nexthop_peer": entry.NexthopPeer, + }} + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/bgp_peers/types.go b/x-pack/metricbeat/module/panos/bgp_peers/types.go new file mode 100644 index 00000000000..cd71f0a7d9d --- /dev/null +++ b/x-pack/metricbeat/module/panos/bgp_peers/types.go @@ -0,0 +1,79 @@ +package bgp_peers + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Entries []Entry `xml:"entry"` +} + +type Entry struct { + Peer string `xml:"peer,attr"` + Vr string `xml:"vr,attr"` + PeerGroup string `xml:"peer-group"` + PeerRouterID string `xml:"peer-router-id"` + RemoteAS int `xml:"remote-as"` + Status string `xml:"status"` + StatusDuration int `xml:"status-duration"` + PasswordSet string `xml:"password-set"` + Passive string `xml:"passive"` + MultiHopTTL int `xml:"multi-hop-ttl"` + PeerAddress string `xml:"peer-address"` + LocalAddress string `xml:"local-address"` + ReflectorClient string `xml:"reflector-client"` + SameConfederation string `xml:"same-confederation"` + AggregateConfedAS string `xml:"aggregate-confed-as"` + PeeringType string `xml:"peering-type"` + ConnectRetryInterval int `xml:"connect-retry-interval"` + OpenDelay int `xml:"open-delay"` + IdleHold int `xml:"idle-hold"` + PrefixLimit int `xml:"prefix-limit"` + Holdtime int `xml:"holdtime"` + HoldtimeConfig int `xml:"holdtime-config"` + Keepalive int `xml:"keepalive"` + KeepaliveConfig int `xml:"keepalive-config"` + MsgUpdateIn int `xml:"msg-update-in"` + MsgUpdateOut int `xml:"msg-update-out"` + MsgTotalIn int `xml:"msg-total-in"` + MsgTotalOut int `xml:"msg-total-out"` + LastUpdateAge int `xml:"last-update-age"` + LastError string `xml:"last-error"` + StatusFlapCounts int `xml:"status-flap-counts"` + EstablishedCounts int `xml:"established-counts"` + ORFEntryReceived int `xml:"ORF-entry-received"` + NexthopSelf string `xml:"nexthop-self"` + NexthopThirdparty string `xml:"nexthop-thirdparty"` + NexthopPeer string `xml:"nexthop-peer"` + Config Config `xml:"config"` + PeerCapability PeerCapability `xml:"peer-capability"` + PrefixCounter PrefixCounter `xml:"prefix-counter"` +} + +type Config struct { + RemovePrivateAS string `xml:"remove-private-as"` +} + +type PeerCapability struct { + List []Capability `xml:"list"` +} + +type Capability struct { + Capability string `xml:"capability"` + Value string `xml:"value"` +} + +type PrefixCounter struct { + Entries []PrefixEntry `xml:"entry"` +} + +type PrefixEntry struct { + AfiSafi string `xml:"afi-safi,attr"` + IncomingTotal int `xml:"incoming-total"` + IncomingAccepted int `xml:"incoming-accepted"` + IncomingRejected int `xml:"incoming-rejected"` + PolicyRejected int `xml:"policy-rejected"` + OutgoingTotal int `xml:"outgoing-total"` + OutgoingAdvertised int `xml:"outgoing-advertised"` +} diff --git a/x-pack/metricbeat/module/panos/filesystem/_meta/data.json b/x-pack/metricbeat/module/panos/filesystem/_meta/data.json index 4a2dd91461f..7ec1ca25f3d 100644 --- a/x-pack/metricbeat/module/panos/filesystem/_meta/data.json +++ b/x-pack/metricbeat/module/panos/filesystem/_meta/data.json @@ -7,12 +7,12 @@ "metricset":{ "host":"localhost", "module":"panos", - "name":"disk", + "name":"filesystem", "rtt":44269 }, "panos":{ - "disk":{ - "example": "disk" + "filesystem":{ + "example": "filesystem" } }, "type":"metricsets" diff --git a/x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc index 163ebb7e0f1..ce37e1eeefc 100644 --- a/x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc +++ b/x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc @@ -1 +1 @@ -This is the disk metricset of the module panos. +This is the filesystem metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml b/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml index 8993a245d31..a15ba687eb6 100644 --- a/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml @@ -1,8 +1,8 @@ -- name: disk +- name: filesystem type: group release: beta description: > - disk + filesystem fields: - name: example type: keyword diff --git a/x-pack/metricbeat/module/panos/filesystem/filesystem.go b/x-pack/metricbeat/module/panos/filesystem/filesystem.go index e3707389dc2..d920f3c84ea 100644 --- a/x-pack/metricbeat/module/panos/filesystem/filesystem.go +++ b/x-pack/metricbeat/module/panos/filesystem/filesystem.go @@ -1,4 +1,4 @@ -package disk +package filesystem import ( "encoding/xml" @@ -33,7 +33,7 @@ type Filesystem struct { } const ( - metricsetName = "disk" + metricsetName = "filesystem" vsys = "shared" query = "" ) @@ -43,7 +43,7 @@ const ( // the MetricSet for each host is defined in the module's configuration. After the // MetricSet has been created then Fetch will begin to be called periodically. func init() { - mb.Registry.MustAddMetricSet("panos", "disk", New) + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) } // MetricSet holds any configuration or state information. It must implement @@ -143,15 +143,17 @@ func getEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { for _, filesystem := range filesystems { event := mb.Event{MetricSetFields: mapstr.M{ - "filesystem.name": filesystem.Name, - "filesystem.size": filesystem.Size, - "filesystem.used": filesystem.Used, - "filesystem.avail": filesystem.Avail, - "filesystem.use_perc": filesystem.UsePerc, - "filesystem.mounted": filesystem.Mounted, - "observer.ip": m.config.HostIp, + "name": filesystem.Name, + "size": filesystem.Size, + "used": filesystem.Used, + "available": filesystem.Avail, + "use_percent": filesystem.UsePerc, + "mounted": filesystem.Mounted, }} event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + } events = append(events, event) } diff --git a/x-pack/metricbeat/module/panos/licenses/licenses.go b/x-pack/metricbeat/module/panos/licenses/licenses.go index f79210ffa96..3cab734dd92 100644 --- a/x-pack/metricbeat/module/panos/licenses/licenses.go +++ b/x-pack/metricbeat/module/panos/licenses/licenses.go @@ -93,18 +93,21 @@ func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { // Initialize the client if err := m.client.Initialize(); err != nil { - log.Fatalf("Failed to initialize client: %s", err) + log.Error("Failed to initialize client: %s", err) + return err } log.Infof("panos_licenses.Fetch initialized client") output, err := m.client.Op(query, vsys, nil, nil) if err != nil { - log.Fatalf("Error: %s", err) + log.Error("Error: %s", err) + return err } err = xml.Unmarshal(output, &response) if err != nil { - log.Fatalf("Error: %s", err) + log.Error("Error: %s", err) + return err } events := getEvents(m, response.Result.Licenses) @@ -123,16 +126,19 @@ func getEvents(m *MetricSet, licenses []License) []mb.Event { for _, license := range licenses { event := mb.Event{MetricSetFields: mapstr.M{ - "license.feature": license.Feature, - "license.description": license.Description, - "license.serial": license.Serial, - "license.issued": license.Issued, - "license.expires": license.Expires, - "license.expired": license.Expired, - "license.auth_code": license.AuthCode, - "observer.ip": m.config.HostIp, + "feature": license.Feature, + "description": license.Description, + "serial": license.Serial, + "issued": license.Issued, + "expires": license.Expires, + "expired": license.Expired, + "auth_code": license.AuthCode, }} event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + } + events = append(events, event) } diff --git a/x-pack/metricbeat/module/panos/system/system.go b/x-pack/metricbeat/module/panos/system/system.go index 9efdfa75f19..913a0145043 100644 --- a/x-pack/metricbeat/module/panos/system/system.go +++ b/x-pack/metricbeat/module/panos/system/system.go @@ -191,9 +191,11 @@ func getEvent(m *MetricSet, input string) mb.Event { "system.swap.free": swapInfo.Free, "system.swap.used": swapInfo.Used, "system.swap.available": swapInfo.Available, - "observer.ip": m.config.HostIp, }} event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + } return event } diff --git a/x-pack/metricbeat/module/panos/types.go b/x-pack/metricbeat/module/panos/types.go index d0024476b62..d451f834dd3 100644 --- a/x-pack/metricbeat/module/panos/types.go +++ b/x-pack/metricbeat/module/panos/types.go @@ -1,11 +1,5 @@ package panos -import ( - "github.com/PaloAltoNetworks/pango" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/logp" -) - const ( ModuleName = "panos" ) @@ -15,14 +9,3 @@ type Config struct { ApiKey string `config:"apiKey"` DebugMode string `config:"apiDebugMode"` } - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - Config Config - Logger *logp.Logger - Client *pango.Firewall -} diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panos.yml.disabled index 9ad01318984..390c493919c 100644 --- a/x-pack/metricbeat/modules.d/panos.yml.disabled +++ b/x-pack/metricbeat/modules.d/panos.yml.disabled @@ -2,8 +2,11 @@ # Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html - module: panos - metricsets: ["licenses"] + metricsets: ["licenses", "system", "filesystem", "bgp_peers"] enabled: false period: 10s - hosts: ["localhost"] + host_ip: "127.0.0.1" + apiKey: "" + apiDebugMode: false + From 4c986a104b76e31936a866b0a033052141af7337 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sun, 1 Sep 2024 18:42:52 -0400 Subject: [PATCH 08/32] temperature metricset --- x-pack/metricbeat/1 | 0 x-pack/metricbeat/include/list.go | 2 + .../module/panos/bgp_peers/bgp_peers.go | 6 +- .../module/panos/filesystem/filesystem.go | 6 +- .../panos/ha_interfaces/_meta/data.json | 19 ++ .../panos/ha_interfaces/_meta/docs.asciidoc | 1 + .../panos/ha_interfaces/_meta/fields.yml | 10 + .../panos/ha_interfaces/ha_interfaces.go | 205 ++++++++++++++++++ .../module/panos/ha_interfaces/type.go | 163 ++++++++++++++ .../module/panos/licenses/licenses.go | 6 +- .../metricbeat/module/panos/system/system.go | 60 ++--- .../module/panos/temperature/_meta/data.json | 19 ++ .../panos/temperature/_meta/docs.asciidoc | 1 + .../module/panos/temperature/_meta/fields.yml | 10 + .../module/panos/temperature/temperature.go | 129 +++++++++++ .../module/panos/temperature/types.go | 30 +++ 16 files changed, 628 insertions(+), 39 deletions(-) create mode 100644 x-pack/metricbeat/1 create mode 100644 x-pack/metricbeat/module/panos/ha_interfaces/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/ha_interfaces/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go create mode 100644 x-pack/metricbeat/module/panos/ha_interfaces/type.go create mode 100644 x-pack/metricbeat/module/panos/temperature/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/temperature/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/temperature/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/temperature/temperature.go create mode 100644 x-pack/metricbeat/module/panos/temperature/types.go diff --git a/x-pack/metricbeat/1 b/x-pack/metricbeat/1 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/x-pack/metricbeat/include/list.go b/x-pack/metricbeat/include/list.go index 5fe8cab6f7a..67b9da8cf84 100644 --- a/x-pack/metricbeat/include/list.go +++ b/x-pack/metricbeat/include/list.go @@ -60,6 +60,8 @@ import ( _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/licenses" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/system" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/bgp_peers" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/ha_interfaces" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/temperature" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/collector" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/remote_write" diff --git a/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go b/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go index 81f78880a9f..9498bd0ab02 100644 --- a/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go +++ b/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go @@ -15,7 +15,7 @@ import ( const ( metricsetName = "bgp_peers" - vsys = "shared" + vsys = "" query = "default" ) @@ -64,7 +64,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // Fetch method implements the data gathering and data conversion to the right // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { +func (m *MetricSet) Fetch(report mb.ReporterV2) error { log := m.Logger() var response Response @@ -93,7 +93,7 @@ func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { log.Debugf("====================================================") log.Debugf("Reporting event: %v", event) log.Debugf("====================================================") - reporter.Event(event) + report.Event(event) } return nil diff --git a/x-pack/metricbeat/module/panos/filesystem/filesystem.go b/x-pack/metricbeat/module/panos/filesystem/filesystem.go index d920f3c84ea..85e6ec0d3c6 100644 --- a/x-pack/metricbeat/module/panos/filesystem/filesystem.go +++ b/x-pack/metricbeat/module/panos/filesystem/filesystem.go @@ -34,7 +34,7 @@ type Filesystem struct { const ( metricsetName = "filesystem" - vsys = "shared" + vsys = "" query = "" ) @@ -83,7 +83,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // Fetch method implements the data gathering and data conversion to the right // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { +func (m *MetricSet) Fetch(report mb.ReporterV2) error { log := m.Logger() var response Response @@ -110,7 +110,7 @@ func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { events := getEvents(m, filesystems) for _, event := range events { - reporter.Event(event) + report.Event(event) } return nil } diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/data.json b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/data.json new file mode 100644 index 00000000000..a3db28e1f82 --- /dev/null +++ b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"ha_interfaces", + "rtt":44269 + }, + "panos":{ + "ha_interfaces":{ + "example": "ha_interfaces" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/docs.asciidoc new file mode 100644 index 00000000000..e172b17e780 --- /dev/null +++ b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the ha_interfaces metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml new file mode 100644 index 00000000000..b34e4595c47 --- /dev/null +++ b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: ha_interfaces + type: group + release: beta + description: > + ha_interfaces + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go new file mode 100644 index 00000000000..69fcf8f9ee4 --- /dev/null +++ b/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go @@ -0,0 +1,205 @@ +package ha_interfaces + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "ha_interfaces" + vsys = "" + query = "" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos ha_interfaces metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_ha_interfaces metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Debug("panos_ha_interfaces.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + events := getEvents(m, response.Result) + for _, event := range events { + report.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, input Result) []mb.Event { + events := make([]mb.Event, 0, len(input.Group.LinkMonitoring.Groups)+1) + group := input.Group + + groupEvent := makeGroupEvent(m, input) + events = append(events, *groupEvent) + linkMonitorEvents := makeLinkMonitoringEvents(m, group.LinkMonitoring) + events = append(events, linkMonitorEvents...) + + return events +} + +func makeGroupEvent(m *MetricSet, input Result) *mb.Event { + group := input.Group + currentTime := time.Now() + event := mb.Event{MetricSetFields: mapstr.M{ + "enabled": input.Enabled, + "mode": group.Mode, + "running_sync": group.RunningSync, + "running_sync_enabled": group.RunningSyncEnabled, + "local_info.version": group.LocalInfo.Version, + "local_info.state": group.LocalInfo.State, + "local_info.state_duration": group.LocalInfo.StateDuration, + "local_info.mgmt_ip": group.LocalInfo.MgmtIP, + "local_info.preemptive": group.LocalInfo.Preemptive, + "local_info.mode": group.LocalInfo.Mode, + "local_info.platform_model": group.LocalInfo.PlatformModel, + "local_info.state_sync": group.LocalInfo.StateSync, + "local_info.state_sync_type": group.LocalInfo.StateSyncType, + "local_info.ha1_ipaddr": group.LocalInfo.HA1IPAddr, + "local_info.ha1_macaddr": group.LocalInfo.HA1MACAddr, + "local_info.ha1_port": group.LocalInfo.HA1Port, + "local_info.ha1_backup_ipaddr": group.LocalInfo.HA1BackupIPAddr, + "local_info.ha1_backup_macaddr": group.LocalInfo.HA1BackupMACAddr, + "local_info.ha1_backup_port": group.LocalInfo.HA1BackupPort, + "local_info.ha1_backup_gateway": group.LocalInfo.HA1BackupGateway, + "local_info.ha2_ipaddr": group.LocalInfo.HA2IPAddr, + "local_info.ha2_macaddr": group.LocalInfo.HA2MACAddr, + "local_info.ha2_port": group.LocalInfo.HA2Port, + "local_info.build_rel": group.LocalInfo.BuildRel, + "local_info.url_version": group.LocalInfo.URLVersion, + "local_info.app_version": group.LocalInfo.AppVersion, + "local_info.iot_version": group.LocalInfo.IoTVersion, + "local_info.av_version": group.LocalInfo.AVVersion, + "local_info.threat_version": group.LocalInfo.ThreatVersion, + "local_info.vpn_client_version": group.LocalInfo.VPNClientVersion, + "local_info.gp_client_version": group.LocalInfo.GPClientVersion, + "peer_info.conn_status": group.PeerInfo.ConnStatus, + "peer_info.state": group.PeerInfo.State, + "peer_info.state_duration": group.PeerInfo.StateDuration, + "peer_info.mgmt_ip": group.PeerInfo.MgmtIP, + "peer_info.preemptive": group.PeerInfo.Preemptive, + "peer_info.mode": group.PeerInfo.Mode, + "peer_info.platform_model": group.PeerInfo.PlatformModel, + "peer_info.priority": group.PeerInfo.Priority, + "peer_info.ha1_ipaddr": group.PeerInfo.HA1IPAddr, + "peer_info.ha1_macaddr": group.PeerInfo.HA1MACAddr, + "peer_info.ha1_backup_ipaddr": group.PeerInfo.HA1BackupIPAddr, + "peer_info.ha1_backup_macaddr": group.PeerInfo.HA1BackupMACAddr, + "peer_info.ha2_ipaddr": group.PeerInfo.HA2IPAddr, + "peer_info.ha2_macaddr": group.PeerInfo.HA2MACAddr, + "peer_info.conn_ha1.status": group.PeerInfo.ConnHA1.Status, + "peer_info.conn_ha1.primary": group.PeerInfo.ConnHA1.Primary, + "peer_info.conn_ha1.description": group.PeerInfo.ConnHA1.Desc, + "peer_info.conn_ha2.status": group.PeerInfo.ConnHA2.Status, + "peer_info.conn_ha2.primary": group.PeerInfo.ConnHA2.Primary, + "peer_info.conn_ha2.description": group.PeerInfo.ConnHA2.Desc, + "peer_info.conn_ha1_backup.status": group.PeerInfo.ConnHA1Backup.Status, + "peer_info.conn_ha1_backup.description": group.PeerInfo.ConnHA1Backup.Desc, + "link_monitoring.enabled": group.LinkMonitoring.Enabled, + }, + } + + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + } + + return &event +} + +func makeLinkMonitoringEvents(m *MetricSet, links LinkMonitoring) []mb.Event { + events := make([]mb.Event, 0, len(links.Groups)) + currentTime := time.Now() + var event mb.Event + for _, group := range links.Groups { + for _, interface_entry := range group.Interface { + event = mb.Event{MetricSetFields: mapstr.M{ + "link_monitoring.enabled": links.Enabled, + "link_monitoring.failure_condition": links.FailureCondition, + "link_monitoring.group.name": group.Name, + "link_monitoring.group.enabled": group.Enabled, + "link_monitoring.group.failure_condition": group.FailureCondition, + "link_monitoring.group.interface.name": interface_entry.Name, + "link_monitoring.group.interface.status": interface_entry.Status, + }} + } + + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/type.go b/x-pack/metricbeat/module/panos/ha_interfaces/type.go new file mode 100644 index 00000000000..85a58765526 --- /dev/null +++ b/x-pack/metricbeat/module/panos/ha_interfaces/type.go @@ -0,0 +1,163 @@ +package ha_interfaces + +import ( + "encoding/xml" +) + +type Response struct { + XMLName xml.Name `xml:"response"` + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Enabled string `xml:"enabled"` + Group Group `xml:"group"` +} + +type Group struct { + Mode string `xml:"mode"` + LocalInfo LocalInfo `xml:"local-info"` + PeerInfo PeerInfo `xml:"peer-info"` + LinkMonitoring LinkMonitoring `xml:"link-monitoring"` + PathMonitoring PathMonitoring `xml:"path-monitoring"` + RunningSync string `xml:"running-sync"` + RunningSyncEnabled string `xml:"running-sync-enabled"` +} + +type LocalInfo struct { + Version string `xml:"version"` + State string `xml:"state"` + StateDuration int `xml:"state-duration"` + MgmtIP string `xml:"mgmt-ip"` + MgmtIPv6 string `xml:"mgmt-ipv6"` + Preemptive string `xml:"preemptive"` + PromotionHold int `xml:"promotion-hold"` + HelloInterval int `xml:"hello-interval"` + HeartbeatInterval int `xml:"heartbeat-interval"` + PreemptHold int `xml:"preempt-hold"` + MonitorFailHoldup int `xml:"monitor-fail-holdup"` + AddonMasterHoldup int `xml:"addon-master-holdup"` + HA1EncryptImported string `xml:"ha1-encrypt-imported"` + Mode string `xml:"mode"` + PlatformModel string `xml:"platform-model"` + Priority int `xml:"priority"` + MaxFlaps int `xml:"max-flaps"` + PreemptFlapCnt int `xml:"preempt-flap-cnt"` + NonfuncFlapCnt int `xml:"nonfunc-flap-cnt"` + StateSync string `xml:"state-sync"` + StateSyncType string `xml:"state-sync-type"` + ActivePassive ActivePassive `xml:"active-passive"` + HA1IPAddr string `xml:"ha1-ipaddr"` + HA1MACAddr string `xml:"ha1-macaddr"` + HA1Port string `xml:"ha1-port"` + HA1EncryptEnable string `xml:"ha1-encrypt-enable"` + HA1LinkMonIntv int `xml:"ha1-link-mon-intv"` + HA1BackupIPAddr string `xml:"ha1-backup-ipaddr"` + HA1BackupMACAddr string `xml:"ha1-backup-macaddr"` + HA1BackupPort string `xml:"ha1-backup-port"` + HA1BackupGateway string `xml:"ha1-backup-gateway"` + HA2IPAddr string `xml:"ha2-ipaddr"` + HA2MACAddr string `xml:"ha2-macaddr"` + HA2Port string `xml:"ha2-port"` + BuildRel string `xml:"build-rel"` + URLVersion string `xml:"url-version"` + AppVersion string `xml:"app-version"` + IoTVersion string `xml:"iot-version"` + AVVersion string `xml:"av-version"` + ThreatVersion string `xml:"threat-version"` + VPNClientVersion string `xml:"vpnclient-version"` + GPClientVersion string `xml:"gpclient-version"` + DLP string `xml:"DLP"` + BuildCompat string `xml:"build-compat"` + URLCompat string `xml:"url-compat"` + AppCompat string `xml:"app-compat"` + IoTCompat string `xml:"iot-compat"` + AVCompat string `xml:"av-compat"` + ThreatCompat string `xml:"threat-compat"` + VPNClientCompat string `xml:"vpnclient-compat"` + GPClientCompat string `xml:"gpclient-compat"` +} + +type ActivePassive struct { + PassiveLinkState string `xml:"passive-link-state"` + MonitorFailHolddown int `xml:"monitor-fail-holddown"` +} + +type PeerInfo struct { + ConnHA1 ConnHA1 `xml:"conn-ha1"` + ConnHA1Backup ConnHA1Backup `xml:"conn-ha1-backup"` + ConnHA2 ConnHA2 `xml:"conn-ha2"` + ConnStatus string `xml:"conn-status"` + Version string `xml:"version"` + State string `xml:"state"` + StateDuration int `xml:"state-duration"` + LastErrorReason string `xml:"last-error-reason"` + LastErrorState string `xml:"last-error-state"` + Preemptive string `xml:"preemptive"` + Mode string `xml:"mode"` + PlatformModel string `xml:"platform-model"` + VMLicense string `xml:"vm-license"` + Priority int `xml:"priority"` + MgmtIP string `xml:"mgmt-ip"` + MgmtIPv6 string `xml:"mgmt-ipv6"` + HA1IPAddr string `xml:"ha1-ipaddr"` + HA1MACAddr string `xml:"ha1-macaddr"` + HA1BackupIPAddr string `xml:"ha1-backup-ipaddr"` + HA1BackupMACAddr string `xml:"ha1-backup-macaddr"` + HA2IPAddr string `xml:"ha2-ipaddr"` + HA2MACAddr string `xml:"ha2-macaddr"` + BuildRel string `xml:"build-rel"` + URLVersion string `xml:"url-version"` + AppVersion string `xml:"app-version"` + IoTVersion string `xml:"iot-version"` + AVVersion string `xml:"av-version"` + ThreatVersion string `xml:"threat-version"` + VPNClientVersion string `xml:"vpnclient-version"` + GPClientVersion string `xml:"gpclient-version"` + DLP string `xml:"DLP"` +} + +type ConnHA1 struct { + Status string `xml:"conn-status"` + Primary string `xml:"conn-primary"` + Desc string `xml:"conn-desc"` +} + +type ConnHA1Backup struct { + Status string `xml:"conn-status"` + Desc string `xml:"conn-desc"` +} + +type ConnHA2 struct { + Primary string `xml:"conn-primary"` + KAEnabled string `xml:"conn-ka-enbled"` + Desc string `xml:"conn-desc"` + Status string `xml:"conn-status"` +} + +type LinkMonitoring struct { + Enabled string `xml:"enabled"` + FailureCondition string `xml:"failure-condition"` + Groups []GroupEntry `xml:"groups>entry"` +} + +type GroupEntry struct { + Name string `xml:"name"` + Enabled string `xml:"enabled"` + FailureCondition string `xml:"failure-condition"` + Interface []InterfaceEntry `xml:"interface>entry"` +} + +type InterfaceEntry struct { + Name string `xml:"name"` + Status string `xml:"status"` +} + +type PathMonitoring struct { + Enabled string `xml:"enabled"` + FailureCondition string `xml:"failure-condition"` + VirtualWire string `xml:"virtual-wire"` + VLAN string `xml:"vlan"` + VirtualRouter string `xml:"virtual-router"` +} diff --git a/x-pack/metricbeat/module/panos/licenses/licenses.go b/x-pack/metricbeat/module/panos/licenses/licenses.go index 3cab734dd92..1f3a7fc49f0 100644 --- a/x-pack/metricbeat/module/panos/licenses/licenses.go +++ b/x-pack/metricbeat/module/panos/licenses/licenses.go @@ -38,7 +38,7 @@ type License struct { const ( metricsetName = "licenses" - vsys = "shared" + vsys = "" query = "" ) @@ -87,7 +87,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // Fetch method implements the data gathering and data conversion to the right // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { +func (m *MetricSet) Fetch(report mb.ReporterV2) error { log := m.Logger() var response Response @@ -113,7 +113,7 @@ func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { events := getEvents(m, response.Result.Licenses) for _, event := range events { - reporter.Event(event) + report.Event(event) } return nil diff --git a/x-pack/metricbeat/module/panos/system/system.go b/x-pack/metricbeat/module/panos/system/system.go index 913a0145043..6e010494b27 100644 --- a/x-pack/metricbeat/module/panos/system/system.go +++ b/x-pack/metricbeat/module/panos/system/system.go @@ -72,7 +72,7 @@ type SwapInfo struct { const ( metricsetName = "system" - vsys = "shared" + vsys = "" query = "" ) @@ -121,7 +121,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // Fetch method implements the data gathering and data conversion to the right // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { +func (m *MetricSet) Fetch(report mb.ReporterV2) error { log := m.Logger() var response Response @@ -145,7 +145,7 @@ func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { } event := getEvent(m, response.Result) - reporter.Event(event) + report.Event(event) return nil } @@ -164,33 +164,33 @@ func getEvent(m *MetricSet, input string) mb.Event { swapInfo := parseSwapInfo(lines[4]) event := mb.Event{MetricSetFields: mapstr.M{ - "system.uptime.days": systemInfo.Uptime.Days, - "system.uptime.hours": systemInfo.Uptime.Hours, - "system.user_count": systemInfo.UserCount, - "system.load_average.1m": systemInfo.LoadAverage.one_minute, - "system.load_average.5m": systemInfo.LoadAverage.five_minute, - "system.load_average.15m": systemInfo.LoadAverage.fifteen_minute, - "system.tasks.total": taskInfo.Total, - "system.tasks.running": taskInfo.Running, - "system.tasks.sleeping": taskInfo.Sleeping, - "system.tasks.stopped": taskInfo.Stopped, - "system.tasks.zombie": taskInfo.Zombie, - "system.cpu.user": cpuInfo.User, - "system.cpu.system": cpuInfo.System, - "system.cpu.nice": cpuInfo.Nice, - "system.cpu.idle": cpuInfo.Idle, - "system.cpu.wait": cpuInfo.Wait, - "system.cpu.hi": cpuInfo.Hi, - "system.cpu.system_int": cpuInfo.SystemInt, - "system.cpu.steal": cpuInfo.Steal, - "system.memory.total": memoryInfo.Total, - "system.memory.free": memoryInfo.Free, - "system.memory.used": memoryInfo.Used, - "system.memory.buffer_cache": memoryInfo.BufferCache, - "system.swap.total": swapInfo.Total, - "system.swap.free": swapInfo.Free, - "system.swap.used": swapInfo.Used, - "system.swap.available": swapInfo.Available, + "uptime.days": systemInfo.Uptime.Days, + "uptime.hours": systemInfo.Uptime.Hours, + "user_count": systemInfo.UserCount, + "load_average.1m": systemInfo.LoadAverage.one_minute, + "load_average.5m": systemInfo.LoadAverage.five_minute, + "load_average.15m": systemInfo.LoadAverage.fifteen_minute, + "tasks.total": taskInfo.Total, + "tasks.running": taskInfo.Running, + "tasks.sleeping": taskInfo.Sleeping, + "tasks.stopped": taskInfo.Stopped, + "tasks.zombie": taskInfo.Zombie, + "cpu.user": cpuInfo.User, + "cpu.system": cpuInfo.System, + "cpu.nice": cpuInfo.Nice, + "cpu.idle": cpuInfo.Idle, + "cpu.wait": cpuInfo.Wait, + "cpu.hi": cpuInfo.Hi, + "cpu.system_int": cpuInfo.SystemInt, + "cpu.steal": cpuInfo.Steal, + "memory.total": memoryInfo.Total, + "memory.free": memoryInfo.Free, + "memory.used": memoryInfo.Used, + "memory.buffer_cache": memoryInfo.BufferCache, + "swap.total": swapInfo.Total, + "swap.free": swapInfo.Free, + "swap.used": swapInfo.Used, + "swap.available": swapInfo.Available, }} event.Timestamp = currentTime event.RootFields = mapstr.M{ diff --git a/x-pack/metricbeat/module/panos/temperature/_meta/data.json b/x-pack/metricbeat/module/panos/temperature/_meta/data.json new file mode 100644 index 00000000000..7054ce03033 --- /dev/null +++ b/x-pack/metricbeat/module/panos/temperature/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"temperature", + "rtt":44269 + }, + "panos":{ + "temperature":{ + "example": "temperature" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/temperature/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/temperature/_meta/docs.asciidoc new file mode 100644 index 00000000000..6f9d6b27f9e --- /dev/null +++ b/x-pack/metricbeat/module/panos/temperature/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the temperature metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml b/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml new file mode 100644 index 00000000000..2d4911ef9cc --- /dev/null +++ b/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: temperature + type: group + release: beta + description: > + temperature + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/temperature/temperature.go b/x-pack/metricbeat/module/panos/temperature/temperature.go new file mode 100644 index 00000000000..d818cf15376 --- /dev/null +++ b/x-pack/metricbeat/module/panos/temperature/temperature.go @@ -0,0 +1,129 @@ +package temperature + +import ( + "encoding/xml" + "fmt" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "temperature" + vsys = "" + query = "" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos temperature metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_temperature metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Debug("panos_temperature. Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + fmt.Printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^temperature response: %+v^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", response) + + events := getEvents(m, &response) + + for _, event := range events { + report.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, response *Response) []mb.Event { + log := m.Logger() + fmt.Printf("^^^^^^^^^^^^^^^^^^^^temperature slots size: %d ^^^^^^^^^^^^^^^^^^^^^^^", len(response.Result.Thermal.Slots)) + events := make([]mb.Event, 0, len(response.Result.Thermal.Slots)) + currentTime := time.Now() + var event mb.Event + for _, slot := range response.Result.Thermal.Slots { + fmt.Printf("^^^^^^^^^^^^^^^^^^^^temperature slot entries size: %d ^^^^^^^^^^^^^^^^^^^^^^^", len(slot.Entries)) + for _, entry := range slot.Entries { + log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) + event = mb.Event{MetricSetFields: mapstr.M{ + + "slot_number": entry.Slot, + "description": entry.Description, + "alarm": entry.Alarm, + "degress_celsius": entry.DegreesCelsius, + "minimum_temp": entry.MinimumTemp, + "maximum_temp": entry.MaximumTemp, + }} + } + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + } + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/temperature/types.go b/x-pack/metricbeat/module/panos/temperature/types.go new file mode 100644 index 00000000000..fd95a25566a --- /dev/null +++ b/x-pack/metricbeat/module/panos/temperature/types.go @@ -0,0 +1,30 @@ +package temperature + +import "encoding/xml" + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Thermal Thermal `xml:"thermal"` +} + +type Thermal struct { + Slots []Slot `xml:",any"` +} + +type Slot struct { + Name xml.Name `xml:",any"` + Entries []Entry `xml:"entry"` +} + +type Entry struct { + Slot int `xml:"slot"` + Description string `xml:"description"` + Alarm bool `xml:"alarm"` + DegreesCelsius float64 `xml:"DegreesC"` + MinimumTemp float64 `xml:"min"` + MaximumTemp float64 `xml:"max"` +} From eff0e0b6c40303974a92768138ec8c56d4c7b4c0 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Mon, 2 Sep 2024 12:54:43 -0400 Subject: [PATCH 09/32] more metricsets --- x-pack/metricbeat/include/list.go | 11 +- .../module/panos/bgp_peers/bgp_peers.go | 12 +- .../module/panos/certificates/_meta/data.json | 19 ++ .../panos/certificates/_meta/docs.asciidoc | 1 + .../panos/certificates/_meta/fields.yml | 10 + .../module/panos/certificates/certificates.go | 178 ++++++++++++++++++ .../module/panos/certificates/types.go | 20 ++ .../module/panos/fans/_meta/data.json | 19 ++ .../module/panos/fans/_meta/docs.asciidoc | 1 + .../module/panos/fans/_meta/fields.yml | 10 + x-pack/metricbeat/module/panos/fans/fans.go | 126 +++++++++++++ x-pack/metricbeat/module/panos/fans/types.go | 26 +++ x-pack/metricbeat/module/panos/fields.go | 2 +- .../module/panos/filesystem/filesystem.go | 24 +-- .../module/panos/filesystem/types.go | 22 +++ .../globalprotect_sessions/_meta/data.json | 19 ++ .../_meta/docs.asciidoc | 1 + .../globalprotect_sessions/_meta/fields.yml | 10 + .../globalprotect_sessions.go | 143 ++++++++++++++ .../panos/globalprotect_sessions/types.go | 37 ++++ .../panos/globalprotect_stats/_meta/data.json | 19 ++ .../globalprotect_stats/_meta/docs.asciidoc | 1 + .../globalprotect_stats/_meta/fields.yml | 10 + .../globalprotect_stats.go | 126 +++++++++++++ .../module/panos/globalprotect_stats/types.go | 18 ++ .../panos/ha_interfaces/ha_interfaces.go | 5 +- .../module/panos/licenses/licenses.go | 24 +-- .../metricbeat/module/panos/licenses/types.go | 20 ++ .../module/panos/logical/_meta/data.json | 19 ++ .../module/panos/logical/_meta/docs.asciidoc | 1 + .../module/panos/logical/_meta/fields.yml | 10 + .../module/panos/logical/logical.go | 129 +++++++++++++ .../metricbeat/module/panos/logical/types.go | 27 +++ .../module/panos/power/_meta/data.json | 19 ++ .../module/panos/power/_meta/docs.asciidoc | 1 + .../module/panos/power/_meta/fields.yml | 10 + x-pack/metricbeat/module/panos/power/power.go | 128 +++++++++++++ x-pack/metricbeat/module/panos/power/types.go | 27 +++ .../metricbeat/module/panos/system/system.go | 66 +------ .../metricbeat/module/panos/system/types.go | 56 ++++++ .../module/panos/temperature/temperature.go | 9 +- .../module/panos/tunnels/_meta/data.json | 19 ++ .../module/panos/tunnels/_meta/docs.asciidoc | 1 + .../module/panos/tunnels/_meta/fields.yml | 10 + .../module/panos/tunnels/tunnels.go | 138 ++++++++++++++ .../metricbeat/module/panos/tunnels/types.go | 32 ++++ .../metricbeat/modules.d/panos.yml.disabled | 17 +- 47 files changed, 1514 insertions(+), 119 deletions(-) create mode 100644 x-pack/metricbeat/module/panos/certificates/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/certificates/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/certificates/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/certificates/certificates.go create mode 100644 x-pack/metricbeat/module/panos/certificates/types.go create mode 100644 x-pack/metricbeat/module/panos/fans/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/fans/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/fans/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/fans/fans.go create mode 100644 x-pack/metricbeat/module/panos/fans/types.go create mode 100644 x-pack/metricbeat/module/panos/filesystem/types.go create mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go create mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/types.go create mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go create mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/types.go create mode 100644 x-pack/metricbeat/module/panos/licenses/types.go create mode 100644 x-pack/metricbeat/module/panos/logical/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/logical/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/logical/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/logical/logical.go create mode 100644 x-pack/metricbeat/module/panos/logical/types.go create mode 100644 x-pack/metricbeat/module/panos/power/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/power/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/power/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/power/power.go create mode 100644 x-pack/metricbeat/module/panos/power/types.go create mode 100644 x-pack/metricbeat/module/panos/system/types.go create mode 100644 x-pack/metricbeat/module/panos/tunnels/_meta/data.json create mode 100644 x-pack/metricbeat/module/panos/tunnels/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/tunnels/tunnels.go create mode 100644 x-pack/metricbeat/module/panos/tunnels/types.go diff --git a/x-pack/metricbeat/include/list.go b/x-pack/metricbeat/include/list.go index 67b9da8cf84..fab59478397 100644 --- a/x-pack/metricbeat/include/list.go +++ b/x-pack/metricbeat/include/list.go @@ -56,12 +56,19 @@ import ( _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/sysmetric" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/tablespace" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/bgp_peers" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/certificates" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/fans" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/filesystem" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/globalprotect_sessions" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/globalprotect_stats" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/ha_interfaces" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/licenses" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/logical" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/power" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/system" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/bgp_peers" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/ha_interfaces" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/temperature" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/tunnels" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/collector" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/remote_write" diff --git a/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go b/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go index 9498bd0ab02..2f821471164 100644 --- a/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go +++ b/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go @@ -49,7 +49,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { if err := base.Module().UnpackConfig(&config); err != nil { return nil, err } - logger.Debugf("panos_licenses metricset config: %v", config) + logger.Debugf("panos_bgp_peers metricset config: %v", config) client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} @@ -73,7 +73,6 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { log.Error("Failed to initialize client: %s", err) return err } - log.Infof("============================= panos/bgp_peers.Fetch initialized client ==============================") output, err := m.client.Op(query, vsys, nil, nil) if err != nil { @@ -90,9 +89,6 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { events := getEvents(m, response.Result.Entries) for _, event := range events { - log.Debugf("====================================================") - log.Debugf("Reporting event: %v", event) - log.Debugf("====================================================") report.Event(event) } @@ -102,13 +98,8 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { func getEvents(m *MetricSet, entries []Entry) []mb.Event { events := make([]mb.Event, 0, len(entries)) currentTime := time.Now() - log := m.Logger() for _, entry := range entries { - log.Debugf("====================================================") - log.Debugf("Processing entry: %v", entry) - log.Debugf("====================================================") - event := mb.Event{MetricSetFields: mapstr.M{ "peer_name": entry.Peer, "virtual_router": entry.Vr, @@ -150,6 +141,7 @@ func getEvents(m *MetricSet, entries []Entry) []mb.Event { event.Timestamp = currentTime event.RootFields = mapstr.M{ "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, } events = append(events, event) diff --git a/x-pack/metricbeat/module/panos/certificates/_meta/data.json b/x-pack/metricbeat/module/panos/certificates/_meta/data.json new file mode 100644 index 00000000000..bb9b24cfa8e --- /dev/null +++ b/x-pack/metricbeat/module/panos/certificates/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"certificates", + "rtt":44269 + }, + "panos":{ + "certificates":{ + "example": "certificates" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/certificates/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/certificates/_meta/docs.asciidoc new file mode 100644 index 00000000000..520981e0d96 --- /dev/null +++ b/x-pack/metricbeat/module/panos/certificates/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the certificates metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml b/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml new file mode 100644 index 00000000000..50aee2d32c3 --- /dev/null +++ b/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: certificates + type: group + release: beta + description: > + certificates + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/certificates/certificates.go b/x-pack/metricbeat/module/panos/certificates/certificates.go new file mode 100644 index 00000000000..5408696f96f --- /dev/null +++ b/x-pack/metricbeat/module/panos/certificates/certificates.go @@ -0,0 +1,178 @@ +package certificates + +import ( + "encoding/xml" + "regexp" + "strings" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "certificates" + vsys = "" + query = "" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos certificates metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Debugf("panos certificates.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + events := getEvents(m, response.Result) + + for _, event := range events { + report.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, input string) []mb.Event { + currentTime := time.Now() + + certificates := parseCertificates(input) + events := make([]mb.Event, 0, len(certificates)) + + for _, certificate := range certificates { + event := mb.Event{ + ModuleFields: mapstr.M{ + "cert_name": certificate.CertName, + "issuer": certificate.Issuer, + "issuer_subject_hash": certificate.IssuerSubjectHash, + "issuer_key_hash": certificate.IssuerKeyHash, + "db_type": certificate.DBType, + "db_exp_date": certificate.DBExpDate, + "db_rev_date": certificate.DBRevDate, + "db_serial_no": certificate.DBSerialNo, + "db_file": certificate.DBFile, + "db_name": certificate.DBName, + "db_status": certificate.DBStatus, + }} + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + } + events = append(events, event) + } + + return events +} + +func parseCertificates(input string) []Certificate { + lines := strings.Split(input, "\n") + pattern := `^[0-9A-Fa-f]{1,40}:[0-9A-Fa-f]{40}([0-9A-Fa-f]{24})?$` + regex := regexp.MustCompile(pattern) + var certificates []Certificate + var currentSN Certificate + + for _, line := range lines { + line = strings.TrimSpace(line) + if regex.MatchString(line) { + if currentSN.CertName != "" { + certificates = append(certificates, currentSN) + currentSN = Certificate{} + } + currentSN.CertName = line + } else if strings.HasPrefix(line, "issuer:") { + currentSN.Issuer = strings.TrimPrefix(line, "issuer: ") + } else if strings.HasPrefix(line, "issuer-subjecthash:") { + currentSN.IssuerSubjectHash = strings.TrimPrefix(line, "issuer-subjecthash: ") + } else if strings.HasPrefix(line, "issuer-keyhash:") { + currentSN.IssuerKeyHash = strings.TrimPrefix(line, "issuer-keyhash: ") + if strings.HasPrefix(currentSN.IssuerKeyHash, "issuer-keyhash:") { + currentSN.IssuerKeyHash = "" + } + } else if strings.HasPrefix(line, "db-type:") { + currentSN.DBType = strings.TrimPrefix(line, "db-type: ") + } else if strings.HasPrefix(line, "db-exp-date:") { + currentSN.DBExpDate = strings.TrimPrefix(line, "db-exp-date: ") + } else if strings.HasPrefix(line, "db-rev-date:") { + currentSN.DBRevDate = strings.TrimPrefix(line, "db-rev-date: ") + } else if strings.HasPrefix(line, "db-serialno:") { + currentSN.DBSerialNo = strings.TrimPrefix(line, "db-serialno: ") + } else if strings.HasPrefix(line, "db-file:") { + currentSN.DBFile = strings.TrimPrefix(line, "db-file: ") + } else if strings.HasPrefix(line, "db-name:") { + currentSN.DBName = strings.TrimPrefix(line, "db-name: ") + } else if strings.HasPrefix(line, "db-status:") { + currentSN.DBStatus = strings.TrimPrefix(line, "db-status: ") + } + } + + if currentSN.Issuer != "" { + certificates = append(certificates, currentSN) + } + + return certificates +} diff --git a/x-pack/metricbeat/module/panos/certificates/types.go b/x-pack/metricbeat/module/panos/certificates/types.go new file mode 100644 index 00000000000..8a86dd28862 --- /dev/null +++ b/x-pack/metricbeat/module/panos/certificates/types.go @@ -0,0 +1,20 @@ +package certificates + +type Response struct { + Status string `xml:"status,attr"` + Result string `xml:"result"` +} + +type Certificate struct { + CertName string + Issuer string + IssuerSubjectHash string + IssuerKeyHash string + DBType string + DBExpDate string + DBRevDate string + DBSerialNo string + DBFile string + DBName string + DBStatus string +} diff --git a/x-pack/metricbeat/module/panos/fans/_meta/data.json b/x-pack/metricbeat/module/panos/fans/_meta/data.json new file mode 100644 index 00000000000..34a471bde92 --- /dev/null +++ b/x-pack/metricbeat/module/panos/fans/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"fans", + "rtt":44269 + }, + "panos":{ + "fans":{ + "example": "fans" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/fans/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/fans/_meta/docs.asciidoc new file mode 100644 index 00000000000..723d4d9db76 --- /dev/null +++ b/x-pack/metricbeat/module/panos/fans/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the fans metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/fans/_meta/fields.yml b/x-pack/metricbeat/module/panos/fans/_meta/fields.yml new file mode 100644 index 00000000000..ae7ae2380a8 --- /dev/null +++ b/x-pack/metricbeat/module/panos/fans/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: fans + type: group + release: beta + description: > + fans + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/fans/fans.go b/x-pack/metricbeat/module/panos/fans/fans.go new file mode 100644 index 00000000000..316e0934489 --- /dev/null +++ b/x-pack/metricbeat/module/panos/fans/fans.go @@ -0,0 +1,126 @@ +package fans + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "fans" + vsys = "" + query = "" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos fans metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_power metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Infof("panos_licenses.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + events := getEvents(m, &response) + + for _, event := range events { + report.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, response *Response) []mb.Event { + log := m.Logger() + events := make([]mb.Event, 0, len(response.Result.Fan.Slots)) + currentTime := time.Now() + var event mb.Event + for _, slot := range response.Result.Fan.Slots { + for _, entry := range slot.Entries { + log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) + event = mb.Event{MetricSetFields: mapstr.M{ + "slot_number": entry.Slot, + "description": entry.Description, + "alarm": entry.Alarm, + "rpm": entry.RPMs, + "min_rpm": entry.Min, + }} + } + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + } + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/fans/types.go b/x-pack/metricbeat/module/panos/fans/types.go new file mode 100644 index 00000000000..7d9c63784d2 --- /dev/null +++ b/x-pack/metricbeat/module/panos/fans/types.go @@ -0,0 +1,26 @@ +package fans + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Fan Fan `xml:"fan"` +} + +type Fan struct { + Slots []Slot `xml:",any"` +} + +type Slot struct { + Entries []Entry `xml:"entry"` +} + +type Entry struct { + Slot int `xml:"slot"` + Description string `xml:"description"` + Alarm string `xml:"alarm"` + RPMs int `xml:"RPMs"` + Min int `xml:"min"` +} diff --git a/x-pack/metricbeat/module/panos/fields.go b/x-pack/metricbeat/module/panos/fields.go index ce9f9aecce7..8cc9f7e3e81 100644 --- a/x-pack/metricbeat/module/panos/fields.go +++ b/x-pack/metricbeat/module/panos/fields.go @@ -19,5 +19,5 @@ func init() { // AssetPanos returns asset data. // This is the base64 encoded zlib format compressed contents of module/panos. func AssetPanos() string { - return "eJzMjztOBDEQRHOforT5XsABGQcx6wJZ45/cXoFvj2a8wHwsshFU5m75Vb8rJjaNbGISBVRXPTUuy/uigEJPI9R4YTUKsJRbcbm6FDWeFID+FyHZu6cCXh29Fb2srogm8Ac/p7ZMjbeS7vkxGTC3mDXKOpm+hyPanP3VXxk2PVZb7r5+fQI/TMiL6zr9kontPRW72/3SO+e5A3vpwdi7G6NQzrAesP+RuTSpDGd4H8h/aP0ZAAD///G74zs=" + return "eJzMlU1uwyAQhfc+xSj7XIBFdz1HNMHPLgoGBGOlvn2VuD8uJu2KltnZI39vvpEFR7pgURTY+dQRiRELRYf786EjirDgBEVnCHdEPZKOJojxTtFTR0TrtzT5frboiAYD2yd1bx3J8YQv/K1kCVA0Rj+H9zcF5nfMFnUewykAMX12Sshb5aN/VDFurRI8H2Q7DF55Cnfrba3jXLBcfeyz3g/ht3pegWvozl0jihmMZkEV/Qf8hjYwsKtinnFbMjYWaUmCqYp3id6Q/Wj9mW2IXqDllJCS8XX+gF+T2t2KsPzFSrKYhvbxwifjBHFgXedgfBTQ0A6s0XCpjn6B3ZK5H41mW0V8h27IO/grYg3rHNyQc72bsOVbUDAFRJY5ooZ6Gd+S/+wcbJWjbY/+R++3AAAA//8yVGcw" } diff --git a/x-pack/metricbeat/module/panos/filesystem/filesystem.go b/x-pack/metricbeat/module/panos/filesystem/filesystem.go index 85e6ec0d3c6..16a01718da0 100644 --- a/x-pack/metricbeat/module/panos/filesystem/filesystem.go +++ b/x-pack/metricbeat/module/panos/filesystem/filesystem.go @@ -13,25 +13,6 @@ import ( "github.com/elastic/elastic-agent-libs/mapstr" ) -type Response struct { - XMLName xml.Name `xml:"response"` - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Data string `xml:",cdata"` -} - -type Filesystem struct { - Name string - Size string - Used string - Avail string - UsePerc string - Mounted string -} - const ( metricsetName = "filesystem" vsys = "" @@ -152,7 +133,10 @@ func getEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { }} event.Timestamp = currentTime event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", } events = append(events, event) diff --git a/x-pack/metricbeat/module/panos/filesystem/types.go b/x-pack/metricbeat/module/panos/filesystem/types.go new file mode 100644 index 00000000000..7e289dbf3d3 --- /dev/null +++ b/x-pack/metricbeat/module/panos/filesystem/types.go @@ -0,0 +1,22 @@ +package filesystem + +import "encoding/xml" + +type Response struct { + XMLName xml.Name `xml:"response"` + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Data string `xml:",cdata"` +} + +type Filesystem struct { + Name string + Size string + Used string + Avail string + UsePerc string + Mounted string +} diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/data.json b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/data.json new file mode 100644 index 00000000000..928bc1fda78 --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"globalprotect_sessions", + "rtt":44269 + }, + "panos":{ + "globalprotect_sessions":{ + "example": "globalprotect_sessions" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/docs.asciidoc new file mode 100644 index 00000000000..d0150573a20 --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the globalprotect_sessions metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml new file mode 100644 index 00000000000..793107dd88e --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: globalprotect_sessions + type: group + release: beta + description: > + globalprotect_sessions + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go b/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go new file mode 100644 index 00000000000..e6ae825dedb --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go @@ -0,0 +1,143 @@ +package globalprotect_sessions + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "globalprotect_sessions" + vsys = "" + query = "" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos globalprotect_sessions metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_licenses metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Infof("panos_licenses.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + events := getEvents(m, response.Result.Sessions) + + for _, event := range events { + report.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, sessions []Session) []mb.Event { + events := make([]mb.Event, 0, len(sessions)) + + currentTime := time.Now() + + for _, session := range sessions { + event := mb.Event{MetricSetFields: mapstr.M{ + "domain": session.Domain, + "is_local": session.IsLocal, + "username": session.Username, + "primary_username": session.PrimaryUsername, + "region_for_config": session.RegionForConfig, + "source_region": session.SourceRegion, + "computer": session.Computer, + "client": session.Client, + "vpn_type": session.VPNType, + "host_id": session.HostID, + "app_version": session.AppVersion, + "virtual_ip": session.VirtualIP, + "virtual_ipv6": session.VirtualIPv6, + "public_ip": session.PublicIP, + "public_ipv6": session.PublicIPv6, + "tunnel_type": session.TunnelType, + "public_connection_ipv6": session.PublicConnectionIPv6, + "client_ip": session.ClientIP, + "login_time": session.LoginTime, + "login_time_utc": session.LoginTimeUTC, + "lifetime": session.Lifetime, + "request_login": session.RequestLogin, + "request_get_config": session.RequestGetConfig, + "request_sslvpn_connect": session.RequestSSLVPNConnect, + }} + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go b/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go new file mode 100644 index 00000000000..e8f90cdbb84 --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go @@ -0,0 +1,37 @@ +package globalprotect_sessions + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Sessions []Session `xml:"entry"` +} + +type Session struct { + Domain string `xml:"domain"` + IsLocal string `xml:"islocal"` + Username string `xml:"username"` + PrimaryUsername string `xml:"primary-username"` + RegionForConfig string `xml:"region-for-config"` + SourceRegion string `xml:"source-region"` + Computer string `xml:"computer"` + Client string `xml:"client"` + VPNType string `xml:"vpn-type"` + HostID string `xml:"host-id"` + AppVersion string `xml:"app-version"` + VirtualIP string `xml:"virtual-ip"` + VirtualIPv6 string `xml:"virtual-ipv6"` + PublicIP string `xml:"public-ip"` + PublicIPv6 string `xml:"public-ipv6"` + TunnelType string `xml:"tunnel-type"` + PublicConnectionIPv6 string `xml:"public-connection-ipv6"` + ClientIP string `xml:"client-ip"` + LoginTime string `xml:"login-time"` + LoginTimeUTC string `xml:"login-time-utc"` + Lifetime string `xml:"lifetime"` + RequestLogin string `xml:"request-login"` + RequestGetConfig string `xml:"request-getconfig"` + RequestSSLVPNConnect string `xml:"request-sslvpnconnect"` +} diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/data.json b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/data.json new file mode 100644 index 00000000000..ad493994cec --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"globalprotect_stats", + "rtt":44269 + }, + "panos":{ + "globalprotect_stats":{ + "example": "globalprotect_stats" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/docs.asciidoc new file mode 100644 index 00000000000..550ca29c6e4 --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the globalprotect_stats metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml new file mode 100644 index 00000000000..e7cfc44fdd4 --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: globalprotect_stats + type: group + release: beta + description: > + globalprotect_stats + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go b/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go new file mode 100644 index 00000000000..0fa3d3a184d --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go @@ -0,0 +1,126 @@ +package globalprotect_stats + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "globalprotect_stats" + vsys = "" + query = "" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos globalprotect_stats metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_licenses metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Infof("panos_licenses.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + events := getEvents(m, response) + + for _, event := range events { + report.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, response Response) []mb.Event { + events := make([]mb.Event, 0, len(response.Result.Gateways)) + + currentTime := time.Now() + totalCurrent := response.Result.TotalCurrentUsers + totalPrevious := response.Result.TotalPreviousUsers + + for _, gateway := range response.Result.Gateways { + event := mb.Event{MetricSetFields: mapstr.M{ + "gateway.name": gateway.Name, + "gateway.current_users": gateway.CurrentUsers, + "gateway.previous_users": gateway.PreviousUsers, + "total_current_users": totalCurrent, + "total_previous_users": totalPrevious, + }} + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/types.go b/x-pack/metricbeat/module/panos/globalprotect_stats/types.go new file mode 100644 index 00000000000..df749584a03 --- /dev/null +++ b/x-pack/metricbeat/module/panos/globalprotect_stats/types.go @@ -0,0 +1,18 @@ +package globalprotect_stats + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Gateways []Gateway `xml:"Gateway"` + TotalCurrentUsers int `xml:"TotalCurrentUsers"` + TotalPreviousUsers int `xml:"TotalPreviousUsers"` +} + +type Gateway struct { + Name string `xml:"name"` + CurrentUsers int `xml:"CurrentUsers"` + PreviousUsers int `xml:"PreviousUsers"` +} diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go index 69fcf8f9ee4..d7eb9852a5e 100644 --- a/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go +++ b/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go @@ -170,7 +170,10 @@ func makeGroupEvent(m *MetricSet, input Result) *mb.Event { event.Timestamp = currentTime event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", } return &event diff --git a/x-pack/metricbeat/module/panos/licenses/licenses.go b/x-pack/metricbeat/module/panos/licenses/licenses.go index 1f3a7fc49f0..50023cf7a01 100644 --- a/x-pack/metricbeat/module/panos/licenses/licenses.go +++ b/x-pack/metricbeat/module/panos/licenses/licenses.go @@ -17,25 +17,6 @@ import ( "github.com/PaloAltoNetworks/pango" ) -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Licenses []License `xml:"licenses>entry"` -} - -type License struct { - Feature string `xml:"feature"` - Description string `xml:"description"` - Serial string `xml:"serial"` - Issued string `xml:"issued"` - Expires string `xml:"expires"` - Expired string `xml:"expired"` - AuthCode string `xml:"authcode"` -} - const ( metricsetName = "licenses" vsys = "" @@ -136,7 +117,10 @@ func getEvents(m *MetricSet, licenses []License) []mb.Event { }} event.Timestamp = currentTime event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", } events = append(events, event) diff --git a/x-pack/metricbeat/module/panos/licenses/types.go b/x-pack/metricbeat/module/panos/licenses/types.go new file mode 100644 index 00000000000..3bad0cc875a --- /dev/null +++ b/x-pack/metricbeat/module/panos/licenses/types.go @@ -0,0 +1,20 @@ +package licenses + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Licenses []License `xml:"licenses>entry"` +} + +type License struct { + Feature string `xml:"feature"` + Description string `xml:"description"` + Serial string `xml:"serial"` + Issued string `xml:"issued"` + Expires string `xml:"expires"` + Expired string `xml:"expired"` + AuthCode string `xml:"authcode"` +} diff --git a/x-pack/metricbeat/module/panos/logical/_meta/data.json b/x-pack/metricbeat/module/panos/logical/_meta/data.json new file mode 100644 index 00000000000..a0fc6777cae --- /dev/null +++ b/x-pack/metricbeat/module/panos/logical/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"logical", + "rtt":44269 + }, + "panos":{ + "logical":{ + "example": "logical" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/logical/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/logical/_meta/docs.asciidoc new file mode 100644 index 00000000000..3ad0493e25b --- /dev/null +++ b/x-pack/metricbeat/module/panos/logical/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the logical metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/logical/_meta/fields.yml b/x-pack/metricbeat/module/panos/logical/_meta/fields.yml new file mode 100644 index 00000000000..4c6afa02327 --- /dev/null +++ b/x-pack/metricbeat/module/panos/logical/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: logical + type: group + release: beta + description: > + logical + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/logical/logical.go b/x-pack/metricbeat/module/panos/logical/logical.go new file mode 100644 index 00000000000..601ce531484 --- /dev/null +++ b/x-pack/metricbeat/module/panos/logical/logical.go @@ -0,0 +1,129 @@ +package logical + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "logical" + vsys = "" + query = "logical" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos logical metricset is beta.") + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_licenses metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Infof("panos_licenses.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + events := getEvents(m, response.Result.Ifnet.LogicalInterfaces) + + for _, event := range events { + report.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, interfaces []LogicalInterface) []mb.Event { + events := make([]mb.Event, 0, len(interfaces)) + + currentTime := time.Now() + + for _, logicalInterface := range interfaces { + event := mb.Event{MetricSetFields: mapstr.M{ + "name": logicalInterface.Name, + "id": logicalInterface.ID, + "tag": logicalInterface.Tag, + "vsys": logicalInterface.Vsys, + "zone": logicalInterface.Zone, + "fwd": logicalInterface.Fwd, + "ip": logicalInterface.IP, + "addr": logicalInterface.Addr, + "dyn_addr": logicalInterface.DynAddr, + "addr6": logicalInterface.Addr6, + }} + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + } + + events = append(events, event) + } + + return events + +} diff --git a/x-pack/metricbeat/module/panos/logical/types.go b/x-pack/metricbeat/module/panos/logical/types.go new file mode 100644 index 00000000000..df51d0a1a79 --- /dev/null +++ b/x-pack/metricbeat/module/panos/logical/types.go @@ -0,0 +1,27 @@ +package logical + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Ifnet Ifnet `xml:"ifnet"` +} + +type Ifnet struct { + LogicalInterfaces []LogicalInterface `xml:"entry"` +} + +type LogicalInterface struct { + Name string `xml:"name"` + ID int `xml:"id"` + Tag int `xml:"tag"` + Vsys int `xml:"vsys"` + Zone string `xml:"zone"` + Fwd string `xml:"fwd"` + IP string `xml:"ip"` + Addr string `xml:"addr"` + DynAddr string `xml:"dyn-addr"` + Addr6 string `xml:"addr6"` +} diff --git a/x-pack/metricbeat/module/panos/power/_meta/data.json b/x-pack/metricbeat/module/panos/power/_meta/data.json new file mode 100644 index 00000000000..0c303cd35c2 --- /dev/null +++ b/x-pack/metricbeat/module/panos/power/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"power", + "rtt":44269 + }, + "panos":{ + "power":{ + "example": "power" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/power/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/power/_meta/docs.asciidoc new file mode 100644 index 00000000000..3e3326a515f --- /dev/null +++ b/x-pack/metricbeat/module/panos/power/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the power metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/power/_meta/fields.yml b/x-pack/metricbeat/module/panos/power/_meta/fields.yml new file mode 100644 index 00000000000..54316afaf6b --- /dev/null +++ b/x-pack/metricbeat/module/panos/power/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: power + type: group + release: beta + description: > + power + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/power/power.go b/x-pack/metricbeat/module/panos/power/power.go new file mode 100644 index 00000000000..607214cf494 --- /dev/null +++ b/x-pack/metricbeat/module/panos/power/power.go @@ -0,0 +1,128 @@ +package power + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "power" + vsys = "" + query = "" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos power metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_power metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Infof("panos_licenses.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + events := getEvents(m, &response) + + for _, event := range events { + report.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, response *Response) []mb.Event { + log := m.Logger() + events := make([]mb.Event, 0, len(response.Result.Power.Slots)) + currentTime := time.Now() + var event mb.Event + for _, slot := range response.Result.Power.Slots { + for _, entry := range slot.Entries { + log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) + event = mb.Event{MetricSetFields: mapstr.M{ + + "slot_number": entry.Slot, + "description": entry.Description, + "alarm": entry.Alarm, + "volts": entry.Volts, + "minimum_volts": entry.MinimumVolts, + "maximum_volts": entry.MaximumVolts, + }} + } + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + } + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/power/types.go b/x-pack/metricbeat/module/panos/power/types.go new file mode 100644 index 00000000000..718eba262ef --- /dev/null +++ b/x-pack/metricbeat/module/panos/power/types.go @@ -0,0 +1,27 @@ +package power + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Power Power `xml:"power"` +} + +type Power struct { + Slots []Slot `xml:",any"` +} + +type Slot struct { + Entries []Entry `xml:"entry"` +} + +type Entry struct { + Slot int `xml:"slot"` + Description string `xml:"description"` + Alarm bool `xml:"alarm"` + Volts float64 `xml:"Volts"` + MinimumVolts float64 `xml:"min"` + MaximumVolts float64 `xml:"max"` +} diff --git a/x-pack/metricbeat/module/panos/system/system.go b/x-pack/metricbeat/module/panos/system/system.go index 6e010494b27..5b81df4b86a 100644 --- a/x-pack/metricbeat/module/panos/system/system.go +++ b/x-pack/metricbeat/module/panos/system/system.go @@ -15,61 +15,6 @@ import ( "github.com/elastic/elastic-agent-libs/mapstr" ) -type Response struct { - Status string `xml:"status,attr"` - Result string `xml:"result"` -} - -type SystemLoad struct { - one_minute float64 - five_minute float64 - fifteen_minute float64 -} - -type Uptime struct { - Days int - Hours string -} - -type SystemInfo struct { - Uptime Uptime - UserCount int - LoadAverage SystemLoad -} - -type TaskInfo struct { - Total int - Running int - Sleeping int - Stopped int - Zombie int -} - -type CPUInfo struct { - User float64 - System float64 - Nice float64 - Idle float64 - Wait float64 - Hi float64 - SystemInt float64 - Steal float64 -} - -type MemoryInfo struct { - Total float64 - Free float64 - Used float64 - BufferCache float64 -} - -type SwapInfo struct { - Total float64 - Free float64 - Used float64 - Available float64 -} - const ( metricsetName = "system" vsys = "" @@ -145,12 +90,12 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { } event := getEvent(m, response.Result) - report.Event(event) + report.Event(*event) return nil } -func getEvent(m *MetricSet, input string) mb.Event { +func getEvent(m *MetricSet, input string) *mb.Event { currentTime := time.Now() // The output is standard "top" output, and we only need the top 5 lines @@ -194,10 +139,13 @@ func getEvent(m *MetricSet, input string) mb.Event { }} event.Timestamp = currentTime event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", } - return event + return &event } func parseSystemInfo(line string) SystemInfo { diff --git a/x-pack/metricbeat/module/panos/system/types.go b/x-pack/metricbeat/module/panos/system/types.go new file mode 100644 index 00000000000..7dfb00e84dc --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/types.go @@ -0,0 +1,56 @@ +package system + +type Response struct { + Status string `xml:"status,attr"` + Result string `xml:"result"` +} + +type SystemLoad struct { + one_minute float64 + five_minute float64 + fifteen_minute float64 +} + +type Uptime struct { + Days int + Hours string +} + +type SystemInfo struct { + Uptime Uptime + UserCount int + LoadAverage SystemLoad +} + +type TaskInfo struct { + Total int + Running int + Sleeping int + Stopped int + Zombie int +} + +type CPUInfo struct { + User float64 + System float64 + Nice float64 + Idle float64 + Wait float64 + Hi float64 + SystemInt float64 + Steal float64 +} + +type MemoryInfo struct { + Total float64 + Free float64 + Used float64 + BufferCache float64 +} + +type SwapInfo struct { + Total float64 + Free float64 + Used float64 + Available float64 +} diff --git a/x-pack/metricbeat/module/panos/temperature/temperature.go b/x-pack/metricbeat/module/panos/temperature/temperature.go index d818cf15376..6bdf53076e8 100644 --- a/x-pack/metricbeat/module/panos/temperature/temperature.go +++ b/x-pack/metricbeat/module/panos/temperature/temperature.go @@ -2,7 +2,6 @@ package temperature import ( "encoding/xml" - "fmt" "time" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" @@ -87,7 +86,6 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { log.Error("Error: %s", err) return err } - fmt.Printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^temperature response: %+v^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", response) events := getEvents(m, &response) @@ -100,12 +98,10 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { func getEvents(m *MetricSet, response *Response) []mb.Event { log := m.Logger() - fmt.Printf("^^^^^^^^^^^^^^^^^^^^temperature slots size: %d ^^^^^^^^^^^^^^^^^^^^^^^", len(response.Result.Thermal.Slots)) events := make([]mb.Event, 0, len(response.Result.Thermal.Slots)) currentTime := time.Now() var event mb.Event for _, slot := range response.Result.Thermal.Slots { - fmt.Printf("^^^^^^^^^^^^^^^^^^^^temperature slot entries size: %d ^^^^^^^^^^^^^^^^^^^^^^^", len(slot.Entries)) for _, entry := range slot.Entries { log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) event = mb.Event{MetricSetFields: mapstr.M{ @@ -120,7 +116,10 @@ func getEvents(m *MetricSet, response *Response) []mb.Event { } event.Timestamp = currentTime event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", } events = append(events, event) } diff --git a/x-pack/metricbeat/module/panos/tunnels/_meta/data.json b/x-pack/metricbeat/module/panos/tunnels/_meta/data.json new file mode 100644 index 00000000000..a7f7868192d --- /dev/null +++ b/x-pack/metricbeat/module/panos/tunnels/_meta/data.json @@ -0,0 +1,19 @@ +{ + "@timestamp":"2016-05-23T08:05:34.853Z", + "beat":{ + "hostname":"beathost", + "name":"beathost" + }, + "metricset":{ + "host":"localhost", + "module":"panos", + "name":"tunnels", + "rtt":44269 + }, + "panos":{ + "tunnels":{ + "example": "tunnels" + } + }, + "type":"metricsets" +} diff --git a/x-pack/metricbeat/module/panos/tunnels/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/tunnels/_meta/docs.asciidoc new file mode 100644 index 00000000000..fd0b68b3aa0 --- /dev/null +++ b/x-pack/metricbeat/module/panos/tunnels/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the tunnels metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml b/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml new file mode 100644 index 00000000000..d50cf0f8b6d --- /dev/null +++ b/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: tunnels + type: group + release: beta + description: > + tunnels + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/tunnels/tunnels.go b/x-pack/metricbeat/module/panos/tunnels/tunnels.go new file mode 100644 index 00000000000..d2b9cf22a17 --- /dev/null +++ b/x-pack/metricbeat/module/panos/tunnels/tunnels.go @@ -0,0 +1,138 @@ +package tunnels + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/PaloAltoNetworks/pango" +) + +const ( + metricsetName = "tunnels" + vsys = "" + query = "" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) +} + +// MetricSet holds any configuration or state information. It must implement +// the mb.MetricSet interface. And this is best achieved by embedding +// mb.BaseMetricSet because it implements all of the required mb.MetricSet +// interface methods except for Fetch. +type MetricSet struct { + mb.BaseMetricSet + config panos.Config + logger *logp.Logger + client *pango.Firewall +} + +// New creates a new instance of the MetricSet. New is responsible for unpacking +// any MetricSet specific configuration options if there are any. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + cfgwarn.Beta("The panos tunnels metricset is beta.") + + config := panos.Config{} + logger := logp.NewLogger(base.FullyQualifiedName()) + + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + logger.Debugf("panos_licenses metricset config: %v", config) + + client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + + return &MetricSet{ + BaseMetricSet: base, + config: config, + logger: logger, + client: client, + }, nil +} + +// Fetch method implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *MetricSet) Fetch(report mb.ReporterV2) error { + log := m.Logger() + var response Response + + // Initialize the client + if err := m.client.Initialize(); err != nil { + log.Error("Failed to initialize client: %s", err) + return err + } + log.Infof("panos_tunnels.Fetch initialized client") + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + log.Error("Error: %s", err) + return err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + log.Error("Error: %s", err) + return err + } + + events := getEvents(m, response.Result.Entries) + + for _, event := range events { + report.Event(event) + } + + return nil +} + +func getEvents(m *MetricSet, entries []Entry) []mb.Event { + events := make([]mb.Event, 0, len(entries)) + + currentTime := time.Now() + + for _, entry := range entries { + event := mb.Event{MetricSetFields: mapstr.M{ + "id": entry.ID, + "name": entry.Name, + "gw": entry.GW, + "TSi_ip": entry.TSiIP, + "TSi_prefix": entry.TSiPrefix, + "TSi_proto": entry.TSiProto, + "TSi_port": entry.TSiPort, + "TSr_ip": entry.TSrIP, + "TSr_prefix": entry.TSrPrefix, + "TSr_proto": entry.TSrProto, + "TSr_port": entry.TSrPort, + "proto": entry.Proto, + "mode": entry.Mode, + "dh": entry.DH, + "enc": entry.Enc, + "hash": entry.Hash, + "life": entry.Life, + "kb": entry.KB, + }} + event.Timestamp = currentTime + event.RootFields = mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + } + + events = append(events, event) + } + + return events + +} diff --git a/x-pack/metricbeat/module/panos/tunnels/types.go b/x-pack/metricbeat/module/panos/tunnels/types.go new file mode 100644 index 00000000000..385198d0a11 --- /dev/null +++ b/x-pack/metricbeat/module/panos/tunnels/types.go @@ -0,0 +1,32 @@ +package tunnels + +type Response struct { + Status string `xml:"status,attr"` + Result Result `xml:"result"` +} + +type Result struct { + Entries []Entry `xml:"entries>entry"` + NTun int `xml:"ntun"` +} + +type Entry struct { + ID int `xml:"id"` + Name string `xml:"name"` + GW string `xml:"gw"` + TSiIP string `xml:"TSi_ip"` + TSiPrefix int `xml:"TSi_prefix"` + TSiProto int `xml:"TSi_proto"` + TSiPort int `xml:"TSi_port"` + TSrIP string `xml:"TSr_ip"` + TSrPrefix int `xml:"TSr_prefix"` + TSrProto int `xml:"TSr_proto"` + TSrPort int `xml:"TSr_port"` + Proto string `xml:"proto"` + Mode string `xml:"mode"` + DH string `xml:"dh"` + Enc string `xml:"enc"` + Hash string `xml:"hash"` + Life int `xml:"life"` + KB int `xml:"kb"` +} diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panos.yml.disabled index 390c493919c..6eb4b9c30cd 100644 --- a/x-pack/metricbeat/modules.d/panos.yml.disabled +++ b/x-pack/metricbeat/modules.d/panos.yml.disabled @@ -2,7 +2,22 @@ # Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html - module: panos - metricsets: ["licenses", "system", "filesystem", "bgp_peers"] + metricsets: + - "bgp_peers" + - "certificates" + - "fans" + - "filesystem" + - "globalprotect_sessions" + - "globalprotect_stats" + - "ha_interfaces" + - "licenses" + - "logical" + - "power" + - "power" + - "system" + - "temperature" + - "tunnels" + enabled: false period: 10s host_ip: "127.0.0.1" From 7a359ea1c380b339e0635a01d6f264cf6b01dc59 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Mon, 2 Sep 2024 13:16:49 -0400 Subject: [PATCH 10/32] use MetricSetFields --- x-pack/metricbeat/module/panos/certificates/certificates.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/metricbeat/module/panos/certificates/certificates.go b/x-pack/metricbeat/module/panos/certificates/certificates.go index 5408696f96f..90d874782fe 100644 --- a/x-pack/metricbeat/module/panos/certificates/certificates.go +++ b/x-pack/metricbeat/module/panos/certificates/certificates.go @@ -105,7 +105,7 @@ func getEvents(m *MetricSet, input string) []mb.Event { for _, certificate := range certificates { event := mb.Event{ - ModuleFields: mapstr.M{ + MetricSetFields: mapstr.M{ "cert_name": certificate.CertName, "issuer": certificate.Issuer, "issuer_subject_hash": certificate.IssuerSubjectHash, From cdafd8ba31fd16d95f22bf6ca421b46cbfb61389 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Mon, 2 Sep 2024 15:45:26 -0400 Subject: [PATCH 11/32] license notices --- x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go | 4 ++++ x-pack/metricbeat/module/panos/bgp_peers/types.go | 3 +++ x-pack/metricbeat/module/panos/certificates/certificates.go | 4 ++++ x-pack/metricbeat/module/panos/certificates/types.go | 4 ++++ x-pack/metricbeat/module/panos/fans/fans.go | 4 ++++ x-pack/metricbeat/module/panos/fans/types.go | 4 ++++ x-pack/metricbeat/module/panos/filesystem/filesystem.go | 4 ++++ x-pack/metricbeat/module/panos/filesystem/types.go | 4 ++++ .../panos/globalprotect_sessions/globalprotect_sessions.go | 4 ++++ .../metricbeat/module/panos/globalprotect_sessions/types.go | 4 ++++ .../module/panos/globalprotect_stats/globalprotect_stats.go | 4 ++++ x-pack/metricbeat/module/panos/globalprotect_stats/types.go | 4 ++++ x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go | 4 ++++ x-pack/metricbeat/module/panos/ha_interfaces/type.go | 4 ++++ x-pack/metricbeat/module/panos/licenses/types.go | 4 ++++ x-pack/metricbeat/module/panos/logical/logical.go | 4 ++++ x-pack/metricbeat/module/panos/logical/types.go | 4 ++++ x-pack/metricbeat/module/panos/power/power.go | 4 ++++ x-pack/metricbeat/module/panos/power/types.go | 4 ++++ x-pack/metricbeat/module/panos/system/system.go | 4 ++++ x-pack/metricbeat/module/panos/system/types.go | 4 ++++ x-pack/metricbeat/module/panos/temperature/temperature.go | 4 ++++ x-pack/metricbeat/module/panos/temperature/types.go | 4 ++++ x-pack/metricbeat/module/panos/tunnels/tunnels.go | 4 ++++ x-pack/metricbeat/module/panos/tunnels/types.go | 4 ++++ 25 files changed, 99 insertions(+) diff --git a/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go b/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go index 2f821471164..b9b7ca6d487 100644 --- a/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go +++ b/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package bgp_peers import ( diff --git a/x-pack/metricbeat/module/panos/bgp_peers/types.go b/x-pack/metricbeat/module/panos/bgp_peers/types.go index cd71f0a7d9d..37fbdaffacb 100644 --- a/x-pack/metricbeat/module/panos/bgp_peers/types.go +++ b/x-pack/metricbeat/module/panos/bgp_peers/types.go @@ -1,3 +1,6 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. package bgp_peers type Response struct { diff --git a/x-pack/metricbeat/module/panos/certificates/certificates.go b/x-pack/metricbeat/module/panos/certificates/certificates.go index 90d874782fe..508e6d68df6 100644 --- a/x-pack/metricbeat/module/panos/certificates/certificates.go +++ b/x-pack/metricbeat/module/panos/certificates/certificates.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package certificates import ( diff --git a/x-pack/metricbeat/module/panos/certificates/types.go b/x-pack/metricbeat/module/panos/certificates/types.go index 8a86dd28862..a06075f2630 100644 --- a/x-pack/metricbeat/module/panos/certificates/types.go +++ b/x-pack/metricbeat/module/panos/certificates/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package certificates type Response struct { diff --git a/x-pack/metricbeat/module/panos/fans/fans.go b/x-pack/metricbeat/module/panos/fans/fans.go index 316e0934489..a8fdbc4ad2e 100644 --- a/x-pack/metricbeat/module/panos/fans/fans.go +++ b/x-pack/metricbeat/module/panos/fans/fans.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package fans import ( diff --git a/x-pack/metricbeat/module/panos/fans/types.go b/x-pack/metricbeat/module/panos/fans/types.go index 7d9c63784d2..172d6865256 100644 --- a/x-pack/metricbeat/module/panos/fans/types.go +++ b/x-pack/metricbeat/module/panos/fans/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package fans type Response struct { diff --git a/x-pack/metricbeat/module/panos/filesystem/filesystem.go b/x-pack/metricbeat/module/panos/filesystem/filesystem.go index 16a01718da0..7ef4b1e9949 100644 --- a/x-pack/metricbeat/module/panos/filesystem/filesystem.go +++ b/x-pack/metricbeat/module/panos/filesystem/filesystem.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package filesystem import ( diff --git a/x-pack/metricbeat/module/panos/filesystem/types.go b/x-pack/metricbeat/module/panos/filesystem/types.go index 7e289dbf3d3..e37c95ac8ef 100644 --- a/x-pack/metricbeat/module/panos/filesystem/types.go +++ b/x-pack/metricbeat/module/panos/filesystem/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package filesystem import "encoding/xml" diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go b/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go index e6ae825dedb..077950e40e2 100644 --- a/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go +++ b/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package globalprotect_sessions import ( diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go b/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go index e8f90cdbb84..635cd77c0b0 100644 --- a/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go +++ b/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package globalprotect_sessions type Response struct { diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go b/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go index 0fa3d3a184d..694bb0ba178 100644 --- a/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go +++ b/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package globalprotect_stats import ( diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/types.go b/x-pack/metricbeat/module/panos/globalprotect_stats/types.go index df749584a03..21f254389c0 100644 --- a/x-pack/metricbeat/module/panos/globalprotect_stats/types.go +++ b/x-pack/metricbeat/module/panos/globalprotect_stats/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package globalprotect_stats type Response struct { diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go index d7eb9852a5e..f710f5ffb85 100644 --- a/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go +++ b/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package ha_interfaces import ( diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/type.go b/x-pack/metricbeat/module/panos/ha_interfaces/type.go index 85a58765526..23432831c3f 100644 --- a/x-pack/metricbeat/module/panos/ha_interfaces/type.go +++ b/x-pack/metricbeat/module/panos/ha_interfaces/type.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package ha_interfaces import ( diff --git a/x-pack/metricbeat/module/panos/licenses/types.go b/x-pack/metricbeat/module/panos/licenses/types.go index 3bad0cc875a..ae74999f514 100644 --- a/x-pack/metricbeat/module/panos/licenses/types.go +++ b/x-pack/metricbeat/module/panos/licenses/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package licenses type Response struct { diff --git a/x-pack/metricbeat/module/panos/logical/logical.go b/x-pack/metricbeat/module/panos/logical/logical.go index 601ce531484..2aceea27e19 100644 --- a/x-pack/metricbeat/module/panos/logical/logical.go +++ b/x-pack/metricbeat/module/panos/logical/logical.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package logical import ( diff --git a/x-pack/metricbeat/module/panos/logical/types.go b/x-pack/metricbeat/module/panos/logical/types.go index df51d0a1a79..ba1f77d917e 100644 --- a/x-pack/metricbeat/module/panos/logical/types.go +++ b/x-pack/metricbeat/module/panos/logical/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package logical type Response struct { diff --git a/x-pack/metricbeat/module/panos/power/power.go b/x-pack/metricbeat/module/panos/power/power.go index 607214cf494..eb111943ad0 100644 --- a/x-pack/metricbeat/module/panos/power/power.go +++ b/x-pack/metricbeat/module/panos/power/power.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package power import ( diff --git a/x-pack/metricbeat/module/panos/power/types.go b/x-pack/metricbeat/module/panos/power/types.go index 718eba262ef..2edc14f5c1f 100644 --- a/x-pack/metricbeat/module/panos/power/types.go +++ b/x-pack/metricbeat/module/panos/power/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package power type Response struct { diff --git a/x-pack/metricbeat/module/panos/system/system.go b/x-pack/metricbeat/module/panos/system/system.go index 5b81df4b86a..73490699f0b 100644 --- a/x-pack/metricbeat/module/panos/system/system.go +++ b/x-pack/metricbeat/module/panos/system/system.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package system import ( diff --git a/x-pack/metricbeat/module/panos/system/types.go b/x-pack/metricbeat/module/panos/system/types.go index 7dfb00e84dc..6b1505dd66f 100644 --- a/x-pack/metricbeat/module/panos/system/types.go +++ b/x-pack/metricbeat/module/panos/system/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package system type Response struct { diff --git a/x-pack/metricbeat/module/panos/temperature/temperature.go b/x-pack/metricbeat/module/panos/temperature/temperature.go index 6bdf53076e8..4948b93a6df 100644 --- a/x-pack/metricbeat/module/panos/temperature/temperature.go +++ b/x-pack/metricbeat/module/panos/temperature/temperature.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package temperature import ( diff --git a/x-pack/metricbeat/module/panos/temperature/types.go b/x-pack/metricbeat/module/panos/temperature/types.go index fd95a25566a..6de010560d4 100644 --- a/x-pack/metricbeat/module/panos/temperature/types.go +++ b/x-pack/metricbeat/module/panos/temperature/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package temperature import "encoding/xml" diff --git a/x-pack/metricbeat/module/panos/tunnels/tunnels.go b/x-pack/metricbeat/module/panos/tunnels/tunnels.go index d2b9cf22a17..8206a8fdea3 100644 --- a/x-pack/metricbeat/module/panos/tunnels/tunnels.go +++ b/x-pack/metricbeat/module/panos/tunnels/tunnels.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package tunnels import ( diff --git a/x-pack/metricbeat/module/panos/tunnels/types.go b/x-pack/metricbeat/module/panos/tunnels/types.go index 385198d0a11..e839a26bfa2 100644 --- a/x-pack/metricbeat/module/panos/tunnels/types.go +++ b/x-pack/metricbeat/module/panos/tunnels/types.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package tunnels type Response struct { From 246d0657386122482788417c4685983f17236966 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Tue, 3 Sep 2024 12:37:21 -0400 Subject: [PATCH 12/32] update fields.yml --- .../module/panos/bgp_peers/_meta/fields.yml | 190 +++++++++++++++++- .../panos/certificates/_meta/fields.yml | 80 +++++++- .../module/panos/fans/_meta/fields.yml | 24 ++- .../module/panos/filesystem/_meta/fields.yml | 29 ++- .../globalprotect_sessions/_meta/fields.yml | 77 ++++++- .../globalprotect_stats/_meta/fields.yml | 21 +- .../panos/ha_interfaces/_meta/fields.yml | 167 ++++++++++++++- .../module/panos/licenses/_meta/fields.yml | 26 ++- .../module/panos/logical/_meta/fields.yml | 35 +++- .../module/panos/power/_meta/fields.yml | 23 ++- .../module/panos/system/_meta/fields.yml | 108 +++++++++- .../module/panos/temperature/_meta/fields.yml | 25 ++- .../module/panos/tunnels/_meta/fields.yml | 59 +++++- 13 files changed, 816 insertions(+), 48 deletions(-) diff --git a/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml b/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml index 16c4779b58f..5c28c249b4a 100644 --- a/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml @@ -4,7 +4,193 @@ description: > bgp_peers fields: - - name: example + - name: peer_name type: keyword description: > - Example field + The name of the peer. + + - name: virtual_router + type: keyword + description: > + The virtual router. + + - name: peer_group + type: keyword + description: > + The peer group. + + - name: peer_router_id + type: keyword + description: > + The peer router ID. + + - name: remote_as_asn + type: keyword + description: > + The remote AS ASN. + + - name: status + type: keyword + description: > + The status. + + - name: status_duration + type: keyword + description: > + The status duration. + + - name: password_set + type: keyword + description: > + The password set. + + - name: passive + type: keyword + description: > + The passive. + + - name: multi_hop_ttl + type: integer + description: > + The multi hop TTL. + + - name: peer_address + type: keyword + description: > + The peer address. + + - name: local_address + type: keyword + description: > + The local address. + + - name: reflector_client + type: keyword + description: > + The reflector client. + + - name: same_confederation + type: keyword + description: > + The same confederation. + + - name: aggregate_confed_as + type: keyword + description: > + The aggregate confed AS. + + - name: peering_type + type: keyword + description: > + The peering type. + + - name: connect_retry_interval + type: integer + description: > + The connect retry interval. + + - name: open_delay + type: integer + description: > + The open delay. + + - name: idle_hold + type: integer + description: > + The idle hold. + + - name: prefix_limit + type: integer + description: > + The prefix limit. + + - name: holdtime + type: integer + description: > + The holdtime. + + - name: holdtime_config + type: integer + description: > + The holdtime config. + + - name: keepalive + type: integer + description: > + The keepalive. + + - name: keepalive_config + type: integer + description: > + The keepalive config. + + - name: msg_update_in + type: integer + description: > + The msg update in. + + - name: msg_update_out + type: integer + description: > + The msg update out. + + - name: msg_total_in + type: integer + description: > + The msg total in. + + - name: msg_total_out + type: integer + description: > + The msg total out. + + - name: last_update_age + type: integer + description: > + The last update age. + + - name: last_error + type: keyword + description: > + The last error. + + - name: status_flap_counts + type: integer + description: > + The status flap counts. + + - name: established_counts + type: integer + description: > + The established counts. + + - name: orf_entry_received + type: keyword + description: > + The ORF entry received. + + - name: nexthop_self + type: keyword + description: > + The nexthop self. + + - name: nexthop_thirdparty + type: keyword + description: > + The nexthop thirdparty. + + - name: nexthop_peer + type: keyword + description: > + The nexthop peer. + + - name: nexthop + type: keyword + description: > + The nexthop. + + - name: nexthop_local + type: keyword + description: > + The nexthop local. + diff --git a/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml b/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml index 50aee2d32c3..d9048c72f1b 100644 --- a/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml @@ -4,7 +4,83 @@ description: > certificates fields: - - name: example + - name: issuer type: keyword description: > - Example field + issuer field + + - name: issuer_subject_hash + type: keyword + description: > + issuer_subject_hash field + + - name: issuer_key_hash + type: keyword + description: > + issuer_key_hash field + + - name: db_type + type: keyword + description: > + db_type field + + - name: db_exp_date + type: keyword + description: > + expiration date, format: 310329235959Z(Mar 29 23:59:59 2031 GMT) + + - name: db_rev_date + type: keyword + description: > + db_rev_date field + + - name: db_serial_no + type: keyword + description: > + db_serial_no field + + - name: db_file + type: keyword + description: > + db_file field + + - name: db_name + type: keyword + description: > + db_name field + + - name: db_status + type: keyword + description: > + db_status field + + + + + + + + + + + + + + + + + + + + +"cert_name": certificate.CertName, + "issuer": certificate.Issuer, + "issuer_subject_hash": certificate.IssuerSubjectHash, + "issuer_key_hash": certificate.IssuerKeyHash, + "db_type": certificate.DBType, + "db_exp_date": certificate.DBExpDate, + "db_rev_date": certificate.DBRevDate, + "db_serial_no": certificate.DBSerialNo, + "db_file": certificate.DBFile, + "db_name": certificate.DBName, + "db_status": certificate.DBStatus, \ No newline at end of file diff --git a/x-pack/metricbeat/module/panos/fans/_meta/fields.yml b/x-pack/metricbeat/module/panos/fans/_meta/fields.yml index ae7ae2380a8..c80aa2dbd26 100644 --- a/x-pack/metricbeat/module/panos/fans/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/fans/_meta/fields.yml @@ -4,7 +4,27 @@ description: > fans fields: - - name: example + - name: slot_number + type: integer + description: > + The number of the hardware slot + + - name: description type: keyword description: > - Example field + The description of the fan + + - name: alarm + type: boollean + description: > + Is there an alarm status of the fan + + - name: rpm + type: integer + description: > + The speed of the fan in RPM + + - name: min_rpm + type: integer + description: > + The minimum speed of the fan in RPM diff --git a/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml b/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml index a15ba687eb6..9441e1dc359 100644 --- a/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml @@ -4,7 +4,32 @@ description: > filesystem fields: - - name: example + - name: name type: keyword description: > - Example field + Filesystem name + + - name: size + type: keyword + description: > + Size, including units, e,g 9.5G. + + - name: used + type: keyword + description: > + Amount used, including units, e.g. 4.0G + + - name: available + type: keyword + description: > + Disk space available, including units, e.g. 5.5G + + - name: use_percent + type: keyword + description: > + Percent of filesystem used + + - name: mounted + type: keyword + description: > + Filesystem mount point diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml index 793107dd88e..d1d0086533e 100644 --- a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml @@ -1,10 +1,77 @@ - name: globalprotect_sessions type: group release: beta - description: > - globalprotect_sessions + description: globalprotect_sessions fields: - - name: example + - name: domain type: keyword - description: > - Example field + description: Domain field + - name: is_local + type: keyword + description: Is Local field + - name: username + type: keyword + description: Username field + - name: primary_username + type: keyword + description: Primary Username field + - name: region_for_config + type: keyword + description: Region for Config field + - name: source_region + type: keyword + description: Source Region field + - name: computer + type: keyword + description: Computer field + - name: client + type: keyword + description: Client field + - name: vpn_type + type: keyword + description: VPN Type field + - name: host_id + type: keyword + description: Host ID field + - name: app_version + type: keyword + description: App Version field + - name: virtual_ip + type: keyword + description: Virtual IP field + - name: virtual_ipv6 + type: keyword + description: Virtual IPv6 field + - name: public_ip + type: keyword + description: Public IP field + - name: public_ipv6 + type: keyword + description: Public IPv6 field + - name: tunnel_type + type: keyword + description: Tunnel Type field + - name: public_connection_ipv6 + type: keyword + description: Public Connection IPv6 field + - name: client_ip + type: keyword + description: Client IP field + - name: login_time + type: keyword + description: Login Time field + - name: login_time_utc + type: keyword + description: Login Time UTC field + - name: lifetime + type: keyword + description: Lifetime field + - name: request_login + type: keyword + description: Request Login field + - name: request_get_config + type: keyword + description: Request Get Config field + - name: request_sslvpn_connect + type: keyword + description: Request SSLVPN Connect field diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml index e7cfc44fdd4..4c73364fb49 100644 --- a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml @@ -4,7 +4,24 @@ description: > globalprotect_stats fields: - - name: example + - name: gateway.name type: keyword description: > - Example field + Name of the GlobalProtect gateway + - name: gateway.current_users + type: integer + description: > + Number of current sessions on the gateway + - name: gateway.previous_users + type: integer + description: > + Number of previous sessions on the gateway + - name: total_current_users + type: integer + description: > + Total current users across all gateways + - name: total_previous_users + type: integer + description: > + Total previous users across all gateways + diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml index b34e4595c47..2f85c920487 100644 --- a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml @@ -1,10 +1,167 @@ - name: ha_interfaces type: group release: beta - description: > - ha_interfaces + description: ha_interfaces fields: - - name: example + - name: enabled type: keyword - description: > - Example field + description: Enabled field + - name: mode + type: keyword + description: Mode field + - name: running_sync + type: keyword + description: Running sync field + - name: running_sync_enabled + type: keyword + description: Running sync enabled field + - name: local_info.version + type: keyword + description: Local info version field + - name: local_info.state + type: keyword + description: Local info state field + - name: local_info.state_duration + type: integer + description: Local info state duration field + - name: local_info.mgmt_ip + type: ip + description: Local info management IP field + - name: local_info.preemptive + type: keyword + description: Local info preemptive field + - name: local_info.mode + type: keyword + description: Local info mode field + - name: local_info.platform_model + type: keyword + description: Local info platform model field + - name: local_info.state_sync + type: keyword + description: Local info state sync field + - name: local_info.state_sync_type + type: keyword + description: Local info state sync type field + - name: local_info.ha1_ipaddr + type: ip + description: Local info HA1 IP address field + - name: local_info.ha1_macaddr + type: keyword + description: Local info HA1 MAC address field + - name: local_info.ha1_port + type: keyword + description: Local info HA1 port field + - name: local_info.ha1_backup_ipaddr + type: ip + description: Local info HA1 backup IP address field + - name: local_info.ha1_backup_macaddr + type: keyword + description: Local info HA1 backup MAC address field + - name: local_info.ha1_backup_port + type: keyword + description: Local info HA1 backup port field + - name: local_info.ha1_backup_gateway + type: keyword + description: Local info HA1 backup gateway field + - name: local_info.ha2_ipaddr + type: keyword + description: Local info HA2 IP address field + - name: local_info.ha2_macaddr + type: keyword + description: Local info HA2 MAC address field + - name: local_info.ha2_port + type: keyword + description: Local info HA2 port field + - name: local_info.build_rel + type: keyword + description: Local info build release field + - name: local_info.url_version + type: keyword + description: Local info URL version field + - name: local_info.app_version + type: keyword + description: Local info app version field + - name: local_info.iot_version + type: keyword + description: Local info IoT version field + - name: local_info.av_version + type: keyword + description: Local info AV version field + - name: local_info.threat_version + type: keyword + description: Local info threat version field + - name: local_info.vpn_client_version + type: keyword + description: Local info VPN client version field + - name: local_info.gp_client_version + type: keyword + description: Local info GP client version field + - name: peer_info.conn_status + type: keyword + description: Peer info connection status field + - name: peer_info.state + type: keyword + description: Peer info state field + - name: peer_info.state_duration + type: integer + description: Peer info state duration field + - name: peer_info.mgmt_ip + type: ip + description: Peer info management IP field + - name: peer_info.preemptive + type: keyword + description: Peer info preemptive field + - name: peer_info.mode + type: keyword + description: Peer info mode field + - name: peer_info.platform_model + type: keyword + description: Peer info platform model field + - name: peer_info.priority + type: keyword + description: Peer info priority field + - name: peer_info.ha1_ipaddr + type: ip + description: Peer info HA1 IP address field + - name: peer_info.ha1_macaddr + type: keyword + description: Peer info HA1 MAC address field + - name: peer_info.ha1_backup_ipaddr + type: keyword + description: Peer info HA1 backup IP address field + - name: peer_info.ha1_backup_macaddr + type: keyword + description: Peer info HA1 backup MAC address field + - name: peer_info.ha2_ipaddr + type: ip + description: Peer info HA2 IP address field + - name: peer_info.ha2_macaddr + type: keyword + description: Peer info HA2 MAC address field + - name: peer_info.conn_ha1.status + type: keyword + description: Peer info HA1 connection status field + - name: peer_info.conn_ha1.primary + type: keyword + description: Peer info HA1 connection primary field + - name: peer_info.conn_ha1.description + type: keyword + description: Peer info HA1 connection description field + - name: peer_info.conn_ha2.status + type: keyword + description: Peer info HA2 connection status field + - name: peer_info.conn_ha2.primary + type: keyword + description: Peer info HA2 connection primary field + - name: peer_info.conn_ha2.description + type: keyword + description: Peer info HA2 connection description field + - name: peer_info.conn_ha1_backup.status + type: keyword + description: Peer info HA1 backup connection status field + - name: peer_info.conn_ha1_backup.description + type: keyword + description: Peer info HA1 backup connection description field + - name: link_monitoring.enabled + type: keyword + description: Link monitoring enabled field diff --git a/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml b/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml index 9c8b9547ae7..e8feed1cf4f 100644 --- a/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml @@ -1,10 +1,26 @@ - name: licenses type: group release: beta - description: > - licenses + description: licenses fields: - - name: example + - name: feature type: keyword - description: > - Example field + description: Feature licensed + - name: description + type: text + description: Description field + - name: serial + type: keyword + description: Serial number of license + - name: issued + type: date + description: Issued date field + - name: expires + type: date + description: Expires date field + - name: expired + type: boolean + description: Expired field + - name: auth_code + type: keyword + description: Auth code field diff --git a/x-pack/metricbeat/module/panos/logical/_meta/fields.yml b/x-pack/metricbeat/module/panos/logical/_meta/fields.yml index 4c6afa02327..f2c844620bb 100644 --- a/x-pack/metricbeat/module/panos/logical/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/logical/_meta/fields.yml @@ -1,10 +1,35 @@ - name: logical type: group release: beta - description: > - logical + description: logical fields: - - name: example + - name: name type: keyword - description: > - Example field + description: Name of logical interface + - name: id + type: keyword + description: ID of logical interface + - name: tag + type: keyword + description: Tag field + - name: vsys + type: keyword + description: Virtual system for this interface + - name: zone + type: keyword + description: Zone field + - name: fwd + type: keyword + description: Forward field + - name: ip + type: ip + description: IP field + - name: addr + type: keyword + description: Address field + - name: dyn_addr + type: keyword + description: Dynamic Address field + - name: addr6 + type: keyword + description: IPv6 Address field diff --git a/x-pack/metricbeat/module/panos/power/_meta/fields.yml b/x-pack/metricbeat/module/panos/power/_meta/fields.yml index 54316afaf6b..59dbae274af 100644 --- a/x-pack/metricbeat/module/panos/power/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/power/_meta/fields.yml @@ -1,10 +1,23 @@ - name: power type: group release: beta - description: > - power + description: power fields: - - name: example + - name: slot_number type: keyword - description: > - Example field + description: Slot number field + - name: description + type: text + description: Description field + - name: alarm + type: boolean + description: Indicates if alarm is active + - name: volts + type: float + description: Current Volts + - name: minimum_volts + type: float + description: Minimum volts recorded + - name: maximum_volts + type: float + description: Maximum volts recorded diff --git a/x-pack/metricbeat/module/panos/system/_meta/fields.yml b/x-pack/metricbeat/module/panos/system/_meta/fields.yml index 9dc174c52d2..1909871d474 100644 --- a/x-pack/metricbeat/module/panos/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/system/_meta/fields.yml @@ -4,7 +4,111 @@ description: > system fields: - - name: example + - name: uptime.days + type: integer + description: > + Uptime in days + - name: uptime.hours type: keyword description: > - Example field + Uptime in hours + - name: user_count + type: integer + description: > + Number of users + - name: load_average.1m + type: float + description: > + Load average in 1 minute + - name: load_average.5m + type: float + description: > + Load average in 5 minutes + - name: load_average.15m + type: float + description: > + Load average in 15 minutes + - name: tasks.total + type: integer + description: > + Total number of tasks + - name: tasks.running + type: integer + description: > + Number of running tasks + - name: tasks.sleeping + type: integer + description: > + Number of sleeping tasks + - name: tasks.stopped + type: integer + description: > + Number of stopped tasks + - name: tasks.zombie + type: integer + description: > + Number of zombie tasks + - name: cpu.user + type: float + description: > + CPU usage by user processes + - name: cpu.system + type: float + description: > + CPU usage by system processes + - name: cpu.nice + type: float + description: > + CPU usage by processes with a positive nice value + - name: cpu.idle + type: float + description: > + CPU idle time + - name: cpu.wait + type: float + description: > + CPU wait time + - name: cpu.hi + type: float + description: > + CPU hardware interrupts + - name: cpu.system_int + type: float + description: > + CPU software interrupts + - name: cpu.steal + type: float + description: > + CPU steal time + - name: memory.total + type: float + description: > + Total memory + - name: memory.free + type: float + description: > + Free memory + - name: memory.used + type: float + description: > + Used memory + - name: memory.buffer_cache + type: keyflaotword + description: > + Memory used for buffers and cache + - name: swap.total + type: float + description: > + Total swap space + - name: swap.free + type: float + description: > + Free swap space + - name: swap.used + type: float + description: > + Used swap space + - name: swap.available + type: float + description: > + Available swap space diff --git a/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml b/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml index 2d4911ef9cc..324bf8288a7 100644 --- a/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml @@ -1,10 +1,23 @@ - name: temperature type: group release: beta - description: > - temperature + description: temperature fields: - - name: example - type: keyword - description: > - Example field + - name: slot_number + type: integer + description: Slot number field + - name: description + type: text + description: Description field + - name: alarm + type: boolean + description: Alarm field + - name: degrees_celsius + type: float + description: Degrees Celsius field + - name: minimum_temp + type: float + description: Minimum temperature field + - name: maximum_temp + type: float + description: Maximum temperature field diff --git a/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml b/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml index d50cf0f8b6d..4296184ef8f 100644 --- a/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml @@ -1,10 +1,59 @@ - name: tunnels type: group release: beta - description: > - tunnels + description: ipsec tunnels fields: - - name: example + - name: id + type: integer + description: ID field + - name: name type: keyword - description: > - Example field + description: Name field + - name: gw + type: keyword + description: Gateway field + - name: TSi_ip + type: ip + description: TSi IP field + - name: TSi_prefix + type: integer + description: TSi Prefix field + - name: TSi_proto + type: integer + description: TSi Protocol field + - name: TSi_port + type: integer + description: TSi Port field + - name: TSr_ip + type: ip + description: TSr IP field + - name: TSr_prefix + type: integer + description: TSr Prefix field + - name: TSr_proto + type: integer + description: TSr Protocol field + - name: TSr_port + type: integer + description: TSr Port field + - name: proto + type: integer + description: Protocol field + - name: mode + type: keyword + description: Mode field + - name: dh + type: keyword + description: DH field + - name: enc + type: keyword + description: Encryption field + - name: hash + type: keyword + description: Hash field + - name: life + type: integer + description: Life field + - name: kb + type: integer + description: KB field From e26bd4f1d8e1ef685a84f22a1602145e4c6821cb Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Tue, 3 Sep 2024 15:06:13 -0400 Subject: [PATCH 13/32] added doc --- .../module/panos/_meta/docs.asciidoc | 86 ++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/x-pack/metricbeat/module/panos/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/_meta/docs.asciidoc index 342d8c6c6df..a800635bf4e 100644 --- a/x-pack/metricbeat/module/panos/_meta/docs.asciidoc +++ b/x-pack/metricbeat/module/panos/_meta/docs.asciidoc @@ -1,2 +1,86 @@ -This is the panos module. +:modulename: panos + +include::{libbeat-dir}/shared/integration-link.asciidoc[] + +:modulename!: + +The panos Metricbeat module uses the Palo Alto [pango](https://pkg.go.dev/github.com/PaloAltoNetworks/pango#section-documentation) package to extract metrics +information from a firewall device via the XML API. + +[float] +=== Dashboards + + +[float] +=== Module-specific configuration notes + +The panos module configuration requires the ip address of the target firewall device and an API Key generated from that firewall. It is assumed +that network access to the firewall is available. All access by the panos module is read-only. + +***Limitations*** +The current version of the module is configured to run against **exactly 1** firewall. Multiple firewalls will require multiple agent configurations. +The module has also not been tested with Panorama, though it should work since it only relies on lower level Client.Op calls to send XML API commands +to the server. + +Required credentials for the `panos` module: + +`host_ip` :: IP address of the firewall - must be network accessible. + +`apiKey`:: An API Key generated via an XML API call to the firewall or via the management dashboard. This + + +[float] +== Metricsets + +[float] +=== `bgp_peers` +This metricset reports information on BGP Peers defined in the firewall. + +[float] +=== `certificates` +This metricset will capture certificates defined on the firewall including expiration dates. + +[float] +=== `fans` +This metricset will collect information from hardware fans (RPMS) and will report if an alarm is active for a given fan. + +[float] +=== `filesystem` +This metricset reports disk usage for filesystems defined on the device, based on df output. + +[float] +=== `globalprotect_sessions` +This metricset will collect metrics on current user sessions established on Global Protect gateways. + +[float] +=== `globalprotect_stats` +This metricset reports the number of user per GlobalProtect gateway and totals across all gateways. + +[float] +=== `ha_interfaces` +This metricset will collect metrics from the device on High Availabilty configuration for interfaces. + +[float] +=== `licenses` +This metricset reports on licenses for sofware features with expiration dates. + +[float] +=== `logical` +This metricset will collect metrics on logical interfaces in the device's network. + +[float] +=== `power` +This metricset reports power usage and alarms. + +[float] +=== `system` +This metricset captures system informate such as uptime, user count, CPU, memory and swap: essentiallyl the first 5 lines of 'top' output. + +[float] +=== `temperature` +This metricset reports temperature for various slots on the device and reports on alarm status. + +[float] +=== `tunnels` +This metricset enumerates ipsec tunnels and their status. From d8dac4d029d35e9b19273668c018b1992e047a79 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sat, 7 Sep 2024 15:26:02 -0400 Subject: [PATCH 14/32] refactor down to 4 metricsets --- x-pack/metricbeat/1 | 0 x-pack/metricbeat/include/list.go | 15 +- .../module/panos/_meta/testdata/bgp_peers.xml | 337 ++++++++++++++++++ .../module/panos/bgp_peers/_meta/data.json | 19 - .../panos/bgp_peers/_meta/docs.asciidoc | 1 - .../module/panos/bgp_peers/_meta/fields.yml | 196 ---------- .../module/panos/bgp_peers/bgp_peers.go | 155 -------- .../module/panos/bgp_peers/types.go | 82 ----- .../module/panos/certificates/_meta/data.json | 19 - .../panos/certificates/_meta/docs.asciidoc | 1 - .../panos/certificates/_meta/fields.yml | 86 ----- .../module/panos/certificates/types.go | 24 -- x-pack/metricbeat/module/panos/client.go | 45 +++ x-pack/metricbeat/module/panos/config.go | 35 ++ x-pack/metricbeat/module/panos/doc.go | 4 + .../module/panos/fans/_meta/docs.asciidoc | 1 - .../module/panos/fans/_meta/fields.yml | 30 -- x-pack/metricbeat/module/panos/fans/types.go | 30 -- x-pack/metricbeat/module/panos/fields.go | 2 +- .../module/panos/filesystem/_meta/data.json | 19 - .../panos/filesystem/_meta/docs.asciidoc | 1 - .../module/panos/filesystem/_meta/fields.yml | 35 -- .../module/panos/filesystem/filesystem.go | 151 -------- .../module/panos/filesystem/types.go | 26 -- .../globalprotect_sessions/_meta/data.json | 19 - .../_meta/docs.asciidoc | 1 - .../globalprotect_sessions/_meta/fields.yml | 77 ---- .../globalprotect_sessions.go | 147 -------- .../panos/globalprotect_sessions/types.go | 41 --- .../panos/globalprotect_stats/_meta/data.json | 19 - .../globalprotect_stats/_meta/docs.asciidoc | 1 - .../globalprotect_stats/_meta/fields.yml | 27 -- .../globalprotect_stats.go | 130 ------- .../module/panos/globalprotect_stats/types.go | 22 -- .../panos/ha_interfaces/_meta/data.json | 19 - .../panos/ha_interfaces/_meta/docs.asciidoc | 1 - .../panos/ha_interfaces/_meta/fields.yml | 167 --------- .../panos/ha_interfaces/ha_interfaces.go | 212 ----------- .../{licenses => interfaces}/_meta/data.json | 6 +- .../panos/interfaces/_meta/docs.asciidoc | 1 + .../module/panos/interfaces/_meta/fields.yml | 10 + .../module/panos/interfaces/ha_interfaces.go | 149 ++++++++ .../panos/interfaces/ifnet_interfaces.go | 115 ++++++ .../type.go => interfaces/interface_types.go} | 109 ++++-- .../fans.go => interfaces/interfaces.go} | 110 +++--- .../module/panos/licenses/_meta/docs.asciidoc | 1 - .../module/panos/licenses/_meta/fields.yml | 26 -- .../metricbeat/module/panos/licenses/types.go | 24 -- .../module/panos/logical/_meta/data.json | 19 - .../module/panos/logical/_meta/docs.asciidoc | 1 - .../module/panos/logical/_meta/fields.yml | 35 -- .../module/panos/logical/logical.go | 133 ------- .../metricbeat/module/panos/logical/types.go | 31 -- .../module/panos/power/_meta/data.json | 19 - .../module/panos/power/_meta/docs.asciidoc | 1 - .../module/panos/power/_meta/fields.yml | 23 -- x-pack/metricbeat/module/panos/power/types.go | 31 -- .../{tunnels => routing}/_meta/data.json | 6 +- .../module/panos/routing/_meta/docs.asciidoc | 1 + .../module/panos/routing/_meta/fields.yml | 10 + .../module/panos/routing/bgp_peers.go | 97 +++++ .../{power/power.go => routing/routing.go} | 109 ++---- .../module/panos/routing/routing_types.go | 83 +++++ .../module/panos/system/_meta/fields.yml | 2 +- .../{certificates => system}/certificates.go | 101 +----- x-pack/metricbeat/module/panos/system/fans.go | 64 ++++ .../module/panos/system/filesystem.go | 100 ++++++ .../metricbeat/module/panos/system/license.go | 65 ++++ .../metricbeat/module/panos/system/power.go | 67 ++++ .../module/panos/system/resources.go | 231 ++++++++++++ .../metricbeat/module/panos/system/system.go | 245 ++++--------- .../module/panos/system/system_types.go | 209 +++++++++++ .../metricbeat/module/panos/system/thermal.go | 68 ++++ .../panos/system/{types.go => types.go.old} | 0 .../module/panos/temperature/_meta/data.json | 19 - .../panos/temperature/_meta/docs.asciidoc | 1 - .../module/panos/temperature/_meta/fields.yml | 23 -- .../module/panos/temperature/temperature.go | 132 ------- .../module/panos/temperature/types.go | 34 -- .../module/panos/tunnels/_meta/docs.asciidoc | 1 - .../module/panos/tunnels/_meta/fields.yml | 59 --- .../module/panos/tunnels/tunnels.go | 142 -------- .../metricbeat/module/panos/tunnels/types.go | 36 -- x-pack/metricbeat/module/panos/types.go | 11 - .../panos/{fans => vpn}/_meta/data.json | 6 +- .../module/panos/vpn/_meta/docs.asciidoc | 1 + .../module/panos/vpn/_meta/fields.yml | 10 + .../module/panos/vpn/gp_sessions.go | 81 +++++ .../metricbeat/module/panos/vpn/gp_stats.go | 64 ++++ x-pack/metricbeat/module/panos/vpn/tunnels.go | 76 ++++ .../{licenses/licenses.go => vpn/vpn.go} | 116 +++--- .../metricbeat/module/panos/vpn/vpn_types.go | 94 +++++ .../metricbeat/modules.d/panos.yml.disabled | 22 +- 93 files changed, 2317 insertions(+), 3110 deletions(-) delete mode 100644 x-pack/metricbeat/1 create mode 100644 x-pack/metricbeat/module/panos/_meta/testdata/bgp_peers.xml delete mode 100644 x-pack/metricbeat/module/panos/bgp_peers/_meta/data.json delete mode 100644 x-pack/metricbeat/module/panos/bgp_peers/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go delete mode 100644 x-pack/metricbeat/module/panos/bgp_peers/types.go delete mode 100644 x-pack/metricbeat/module/panos/certificates/_meta/data.json delete mode 100644 x-pack/metricbeat/module/panos/certificates/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/certificates/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/certificates/types.go create mode 100644 x-pack/metricbeat/module/panos/client.go create mode 100644 x-pack/metricbeat/module/panos/config.go delete mode 100644 x-pack/metricbeat/module/panos/fans/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/fans/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/fans/types.go delete mode 100644 x-pack/metricbeat/module/panos/filesystem/_meta/data.json delete mode 100644 x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/filesystem/filesystem.go delete mode 100644 x-pack/metricbeat/module/panos/filesystem/types.go delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/data.json delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_sessions/types.go delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/_meta/data.json delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go delete mode 100644 x-pack/metricbeat/module/panos/globalprotect_stats/types.go delete mode 100644 x-pack/metricbeat/module/panos/ha_interfaces/_meta/data.json delete mode 100644 x-pack/metricbeat/module/panos/ha_interfaces/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go rename x-pack/metricbeat/module/panos/{licenses => interfaces}/_meta/data.json (76%) create mode 100644 x-pack/metricbeat/module/panos/interfaces/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/interfaces/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go create mode 100644 x-pack/metricbeat/module/panos/interfaces/ifnet_interfaces.go rename x-pack/metricbeat/module/panos/{ha_interfaces/type.go => interfaces/interface_types.go} (70%) rename x-pack/metricbeat/module/panos/{fans/fans.go => interfaces/interfaces.go} (51%) delete mode 100644 x-pack/metricbeat/module/panos/licenses/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/licenses/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/licenses/types.go delete mode 100644 x-pack/metricbeat/module/panos/logical/_meta/data.json delete mode 100644 x-pack/metricbeat/module/panos/logical/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/logical/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/logical/logical.go delete mode 100644 x-pack/metricbeat/module/panos/logical/types.go delete mode 100644 x-pack/metricbeat/module/panos/power/_meta/data.json delete mode 100644 x-pack/metricbeat/module/panos/power/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/power/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/power/types.go rename x-pack/metricbeat/module/panos/{tunnels => routing}/_meta/data.json (77%) create mode 100644 x-pack/metricbeat/module/panos/routing/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/routing/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/routing/bgp_peers.go rename x-pack/metricbeat/module/panos/{power/power.go => routing/routing.go} (50%) create mode 100644 x-pack/metricbeat/module/panos/routing/routing_types.go rename x-pack/metricbeat/module/panos/{certificates => system}/certificates.go (54%) create mode 100644 x-pack/metricbeat/module/panos/system/fans.go create mode 100644 x-pack/metricbeat/module/panos/system/filesystem.go create mode 100644 x-pack/metricbeat/module/panos/system/license.go create mode 100644 x-pack/metricbeat/module/panos/system/power.go create mode 100644 x-pack/metricbeat/module/panos/system/resources.go create mode 100644 x-pack/metricbeat/module/panos/system/system_types.go create mode 100644 x-pack/metricbeat/module/panos/system/thermal.go rename x-pack/metricbeat/module/panos/system/{types.go => types.go.old} (100%) delete mode 100644 x-pack/metricbeat/module/panos/temperature/_meta/data.json delete mode 100644 x-pack/metricbeat/module/panos/temperature/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/temperature/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/temperature/temperature.go delete mode 100644 x-pack/metricbeat/module/panos/temperature/types.go delete mode 100644 x-pack/metricbeat/module/panos/tunnels/_meta/docs.asciidoc delete mode 100644 x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/tunnels/tunnels.go delete mode 100644 x-pack/metricbeat/module/panos/tunnels/types.go delete mode 100644 x-pack/metricbeat/module/panos/types.go rename x-pack/metricbeat/module/panos/{fans => vpn}/_meta/data.json (80%) create mode 100644 x-pack/metricbeat/module/panos/vpn/_meta/docs.asciidoc create mode 100644 x-pack/metricbeat/module/panos/vpn/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panos/vpn/gp_sessions.go create mode 100644 x-pack/metricbeat/module/panos/vpn/gp_stats.go create mode 100644 x-pack/metricbeat/module/panos/vpn/tunnels.go rename x-pack/metricbeat/module/panos/{licenses/licenses.go => vpn/vpn.go} (52%) create mode 100644 x-pack/metricbeat/module/panos/vpn/vpn_types.go diff --git a/x-pack/metricbeat/1 b/x-pack/metricbeat/1 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/x-pack/metricbeat/include/list.go b/x-pack/metricbeat/include/list.go index fab59478397..289874d1ba1 100644 --- a/x-pack/metricbeat/include/list.go +++ b/x-pack/metricbeat/include/list.go @@ -56,19 +56,10 @@ import ( _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/sysmetric" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/tablespace" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/bgp_peers" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/certificates" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/fans" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/filesystem" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/globalprotect_sessions" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/globalprotect_stats" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/ha_interfaces" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/licenses" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/logical" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/power" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/interfaces" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/routing" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/system" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/temperature" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/tunnels" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/vpn" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/collector" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/remote_write" diff --git a/x-pack/metricbeat/module/panos/_meta/testdata/bgp_peers.xml b/x-pack/metricbeat/module/panos/_meta/testdata/bgp_peers.xml new file mode 100644 index 00000000000..1b975b9ae2d --- /dev/null +++ b/x-pack/metricbeat/module/panos/_meta/testdata/bgp_peers.xml @@ -0,0 +1,337 @@ + + + + POC + 10.100.11.2 + 64711 + Established + 17840221 + no + no + 1 + 1.1.1.1:179 + 1.1.1.1:43896 + not-client + no + yes + Unspecified + 15 + 0 + 15 + 0 + 90 + 90 + 30 + 30 + 7221 + 10242 + 314758 + 361880 + 26 + + 4 + 1 + 0 + no + yes + no + + no + + + + Multiprotocol Extensions(1) + IPv4 Unicast + + + Route Refresh(2) + yes + + + Extended Next Hop Encoding(5) + 000100010002000100800002 + + + Graceful Restart(64) + 007800010100 + + + 4-Byte AS Number(65) + 64711 + + + Deprecated(66) + yes + + + Dynamic Capability(67) + 020140 + + + Route Refresh (Cisco)(128) + yes + + + + + 12 + 12 + 0 + 0 + 78 + 78 + + + + + POC + 1.1.1.1 + 64711 + Established + 17840224 + no + no + 1 + 1.1.1.1:179 + 1.1.1.1:52945 + not-client + no + yes + Unspecified + 15 + 0 + 15 + 0 + 90 + 90 + 30 + 30 + 7244 + 10235 + 314777 + 362006 + 1 + + 3 + 1 + 0 + no + yes + no + + no + + + + Multiprotocol Extensions(1) + IPv4 Unicast + + + Route Refresh(2) + yes + + + Extended Next Hop Encoding(5) + 000100010002000100800002 + + + Graceful Restart(64) + 007800010100 + + + 4-Byte AS Number(65) + 64711 + + + Deprecated(66) + yes + + + Dynamic Capability(67) + 020140 + + + Route Refresh (Cisco)(128) + yes + + + + + 12 + 12 + 0 + 0 + 78 + 78 + + + + + POC + 1.1.1.1 + 64712 + Established + 17840219 + no + no + 1 + 1.1.1.1:179 + 1.1.1.1:49498 + not-client + no + yes + Unspecified + 15 + 0 + 15 + 0 + 90 + 90 + 30 + 30 + 7224 + 10237 + 314761 + 361928 + 26 + + 4 + 1 + 0 + no + yes + no + + no + + + + Multiprotocol Extensions(1) + IPv4 Unicast + + + Route Refresh(2) + yes + + + Extended Next Hop Encoding(5) + 000100010002000100800002 + + + Graceful Restart(64) + 007800010100 + + + 4-Byte AS Number(65) + 64712 + + + Deprecated(66) + yes + + + Dynamic Capability(67) + 020140 + + + Route Refresh (Cisco)(128) + yes + + + + + 12 + 12 + 0 + 0 + 84 + 84 + + + + + POC + 1.1.1.1 + 64712 + Established + 17840218 + no + no + 1 + 1.1.1.1:179 + 1.1.1.1:55026 + not-client + no + yes + Unspecified + 15 + 0 + 15 + 0 + 90 + 90 + 30 + 30 + 7183 + 10236 + 314725 + 362057 + 26 + + 4 + 1 + 0 + no + yes + no + + no + + + + Multiprotocol Extensions(1) + IPv4 Unicast + + + Route Refresh(2) + yes + + + Extended Next Hop Encoding(5) + 000100010002000100800002 + + + Graceful Restart(64) + 007800010100 + + + 4-Byte AS Number(65) + 64712 + + + Deprecated(66) + yes + + + Dynamic Capability(67) + 020140 + + + Route Refresh (Cisco)(128) + yes + + + + + 12 + 12 + 0 + 0 + 84 + 84 + + + + + + \ No newline at end of file diff --git a/x-pack/metricbeat/module/panos/bgp_peers/_meta/data.json b/x-pack/metricbeat/module/panos/bgp_peers/_meta/data.json deleted file mode 100644 index aedd8f2eb7f..00000000000 --- a/x-pack/metricbeat/module/panos/bgp_peers/_meta/data.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "@timestamp":"2016-05-23T08:05:34.853Z", - "beat":{ - "hostname":"beathost", - "name":"beathost" - }, - "metricset":{ - "host":"localhost", - "module":"panos", - "name":"bgp_peers", - "rtt":44269 - }, - "panos":{ - "bgp_peers":{ - "example": "bgp_peers" - } - }, - "type":"metricsets" -} diff --git a/x-pack/metricbeat/module/panos/bgp_peers/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/bgp_peers/_meta/docs.asciidoc deleted file mode 100644 index 369e008b9b3..00000000000 --- a/x-pack/metricbeat/module/panos/bgp_peers/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the bgp_peers metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml b/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml deleted file mode 100644 index 5c28c249b4a..00000000000 --- a/x-pack/metricbeat/module/panos/bgp_peers/_meta/fields.yml +++ /dev/null @@ -1,196 +0,0 @@ -- name: bgp_peers - type: group - release: beta - description: > - bgp_peers - fields: - - name: peer_name - type: keyword - description: > - The name of the peer. - - - name: virtual_router - type: keyword - description: > - The virtual router. - - - name: peer_group - type: keyword - description: > - The peer group. - - - name: peer_router_id - type: keyword - description: > - The peer router ID. - - - name: remote_as_asn - type: keyword - description: > - The remote AS ASN. - - - name: status - type: keyword - description: > - The status. - - - name: status_duration - type: keyword - description: > - The status duration. - - - name: password_set - type: keyword - description: > - The password set. - - - name: passive - type: keyword - description: > - The passive. - - - name: multi_hop_ttl - type: integer - description: > - The multi hop TTL. - - - name: peer_address - type: keyword - description: > - The peer address. - - - name: local_address - type: keyword - description: > - The local address. - - - name: reflector_client - type: keyword - description: > - The reflector client. - - - name: same_confederation - type: keyword - description: > - The same confederation. - - - name: aggregate_confed_as - type: keyword - description: > - The aggregate confed AS. - - - name: peering_type - type: keyword - description: > - The peering type. - - - name: connect_retry_interval - type: integer - description: > - The connect retry interval. - - - name: open_delay - type: integer - description: > - The open delay. - - - name: idle_hold - type: integer - description: > - The idle hold. - - - name: prefix_limit - type: integer - description: > - The prefix limit. - - - name: holdtime - type: integer - description: > - The holdtime. - - - name: holdtime_config - type: integer - description: > - The holdtime config. - - - name: keepalive - type: integer - description: > - The keepalive. - - - name: keepalive_config - type: integer - description: > - The keepalive config. - - - name: msg_update_in - type: integer - description: > - The msg update in. - - - name: msg_update_out - type: integer - description: > - The msg update out. - - - name: msg_total_in - type: integer - description: > - The msg total in. - - - name: msg_total_out - type: integer - description: > - The msg total out. - - - name: last_update_age - type: integer - description: > - The last update age. - - - name: last_error - type: keyword - description: > - The last error. - - - name: status_flap_counts - type: integer - description: > - The status flap counts. - - - name: established_counts - type: integer - description: > - The established counts. - - - name: orf_entry_received - type: keyword - description: > - The ORF entry received. - - - name: nexthop_self - type: keyword - description: > - The nexthop self. - - - name: nexthop_thirdparty - type: keyword - description: > - The nexthop thirdparty. - - - name: nexthop_peer - type: keyword - description: > - The nexthop peer. - - - name: nexthop - type: keyword - description: > - The nexthop. - - - name: nexthop_local - type: keyword - description: > - The nexthop local. - diff --git a/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go b/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go deleted file mode 100644 index b9b7ca6d487..00000000000 --- a/x-pack/metricbeat/module/panos/bgp_peers/bgp_peers.go +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package bgp_peers - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" -) - -const ( - metricsetName = "bgp_peers" - vsys = "" - query = "default" -) - -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - config panos.Config - logger *logp.Logger - client *pango.Firewall -} - -// New creates a new instance of the MetricSet. New is responsible for unpacking -// any MetricSet specific configuration options if there are any. -func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos licenses metricset is beta.") - - config := panos.Config{} - logger := logp.NewLogger(base.FullyQualifiedName()) - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - logger.Debugf("panos_bgp_peers metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - - return &MetricSet{ - BaseMetricSet: base, - config: config, - logger: logger, - client: client, - }, nil -} - -// Fetch method implements the data gathering and data conversion to the right -// format. It publishes the event which is then forwarded to the output. In case -// of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - log.Error("Error: %s", err) - return err - } - - events := getEvents(m, response.Result.Entries) - - for _, event := range events { - report.Event(event) - } - - return nil -} - -func getEvents(m *MetricSet, entries []Entry) []mb.Event { - events := make([]mb.Event, 0, len(entries)) - currentTime := time.Now() - - for _, entry := range entries { - event := mb.Event{MetricSetFields: mapstr.M{ - "peer_name": entry.Peer, - "virtual_router": entry.Vr, - "peer_group": entry.PeerGroup, - "peer_router_id": entry.PeerRouterID, - "remote_as_asn": entry.RemoteAS, - "status": entry.Status, - "status_duration": entry.StatusDuration, - "password_set": entry.PasswordSet, - "passive": entry.Passive, - "multi_hop_ttl": entry.MultiHopTTL, - "peer_address": entry.PeerAddress, - "local_address": entry.LocalAddress, - "reflector_client": entry.ReflectorClient, - "same_confederation": entry.SameConfederation, - "aggregate_confed_as": entry.AggregateConfedAS, - "peering_type": entry.PeeringType, - "connect_retry_interval": entry.ConnectRetryInterval, - "open_delay": entry.OpenDelay, - "idle_hold": entry.IdleHold, - "prefix_limit": entry.PrefixLimit, - "holdtime": entry.Holdtime, - "holdtime_config": entry.HoldtimeConfig, - "keepalive": entry.Keepalive, - "keepalive_config": entry.KeepaliveConfig, - "msg_update_in": entry.MsgUpdateIn, - "msg_update_out": entry.MsgUpdateOut, - "msg_total_in": entry.MsgTotalIn, - "msg_total_out": entry.MsgTotalOut, - "last_update_age": entry.LastUpdateAge, - "last_error": entry.LastError, - "status_flap_counts": entry.StatusFlapCounts, - "established_counts": entry.EstablishedCounts, - "orf_entry_received": entry.ORFEntryReceived, - "nexthop_self": entry.NexthopSelf, - "nexthop_thirdparty": entry.NexthopThirdparty, - "nexthop_peer": entry.NexthopPeer, - }} - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - } - - events = append(events, event) - } - - return events -} diff --git a/x-pack/metricbeat/module/panos/bgp_peers/types.go b/x-pack/metricbeat/module/panos/bgp_peers/types.go deleted file mode 100644 index 37fbdaffacb..00000000000 --- a/x-pack/metricbeat/module/panos/bgp_peers/types.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. -package bgp_peers - -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Entries []Entry `xml:"entry"` -} - -type Entry struct { - Peer string `xml:"peer,attr"` - Vr string `xml:"vr,attr"` - PeerGroup string `xml:"peer-group"` - PeerRouterID string `xml:"peer-router-id"` - RemoteAS int `xml:"remote-as"` - Status string `xml:"status"` - StatusDuration int `xml:"status-duration"` - PasswordSet string `xml:"password-set"` - Passive string `xml:"passive"` - MultiHopTTL int `xml:"multi-hop-ttl"` - PeerAddress string `xml:"peer-address"` - LocalAddress string `xml:"local-address"` - ReflectorClient string `xml:"reflector-client"` - SameConfederation string `xml:"same-confederation"` - AggregateConfedAS string `xml:"aggregate-confed-as"` - PeeringType string `xml:"peering-type"` - ConnectRetryInterval int `xml:"connect-retry-interval"` - OpenDelay int `xml:"open-delay"` - IdleHold int `xml:"idle-hold"` - PrefixLimit int `xml:"prefix-limit"` - Holdtime int `xml:"holdtime"` - HoldtimeConfig int `xml:"holdtime-config"` - Keepalive int `xml:"keepalive"` - KeepaliveConfig int `xml:"keepalive-config"` - MsgUpdateIn int `xml:"msg-update-in"` - MsgUpdateOut int `xml:"msg-update-out"` - MsgTotalIn int `xml:"msg-total-in"` - MsgTotalOut int `xml:"msg-total-out"` - LastUpdateAge int `xml:"last-update-age"` - LastError string `xml:"last-error"` - StatusFlapCounts int `xml:"status-flap-counts"` - EstablishedCounts int `xml:"established-counts"` - ORFEntryReceived int `xml:"ORF-entry-received"` - NexthopSelf string `xml:"nexthop-self"` - NexthopThirdparty string `xml:"nexthop-thirdparty"` - NexthopPeer string `xml:"nexthop-peer"` - Config Config `xml:"config"` - PeerCapability PeerCapability `xml:"peer-capability"` - PrefixCounter PrefixCounter `xml:"prefix-counter"` -} - -type Config struct { - RemovePrivateAS string `xml:"remove-private-as"` -} - -type PeerCapability struct { - List []Capability `xml:"list"` -} - -type Capability struct { - Capability string `xml:"capability"` - Value string `xml:"value"` -} - -type PrefixCounter struct { - Entries []PrefixEntry `xml:"entry"` -} - -type PrefixEntry struct { - AfiSafi string `xml:"afi-safi,attr"` - IncomingTotal int `xml:"incoming-total"` - IncomingAccepted int `xml:"incoming-accepted"` - IncomingRejected int `xml:"incoming-rejected"` - PolicyRejected int `xml:"policy-rejected"` - OutgoingTotal int `xml:"outgoing-total"` - OutgoingAdvertised int `xml:"outgoing-advertised"` -} diff --git a/x-pack/metricbeat/module/panos/certificates/_meta/data.json b/x-pack/metricbeat/module/panos/certificates/_meta/data.json deleted file mode 100644 index bb9b24cfa8e..00000000000 --- a/x-pack/metricbeat/module/panos/certificates/_meta/data.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "@timestamp":"2016-05-23T08:05:34.853Z", - "beat":{ - "hostname":"beathost", - "name":"beathost" - }, - "metricset":{ - "host":"localhost", - "module":"panos", - "name":"certificates", - "rtt":44269 - }, - "panos":{ - "certificates":{ - "example": "certificates" - } - }, - "type":"metricsets" -} diff --git a/x-pack/metricbeat/module/panos/certificates/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/certificates/_meta/docs.asciidoc deleted file mode 100644 index 520981e0d96..00000000000 --- a/x-pack/metricbeat/module/panos/certificates/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the certificates metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml b/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml deleted file mode 100644 index d9048c72f1b..00000000000 --- a/x-pack/metricbeat/module/panos/certificates/_meta/fields.yml +++ /dev/null @@ -1,86 +0,0 @@ -- name: certificates - type: group - release: beta - description: > - certificates - fields: - - name: issuer - type: keyword - description: > - issuer field - - - name: issuer_subject_hash - type: keyword - description: > - issuer_subject_hash field - - - name: issuer_key_hash - type: keyword - description: > - issuer_key_hash field - - - name: db_type - type: keyword - description: > - db_type field - - - name: db_exp_date - type: keyword - description: > - expiration date, format: 310329235959Z(Mar 29 23:59:59 2031 GMT) - - - name: db_rev_date - type: keyword - description: > - db_rev_date field - - - name: db_serial_no - type: keyword - description: > - db_serial_no field - - - name: db_file - type: keyword - description: > - db_file field - - - name: db_name - type: keyword - description: > - db_name field - - - name: db_status - type: keyword - description: > - db_status field - - - - - - - - - - - - - - - - - - - - -"cert_name": certificate.CertName, - "issuer": certificate.Issuer, - "issuer_subject_hash": certificate.IssuerSubjectHash, - "issuer_key_hash": certificate.IssuerKeyHash, - "db_type": certificate.DBType, - "db_exp_date": certificate.DBExpDate, - "db_rev_date": certificate.DBRevDate, - "db_serial_no": certificate.DBSerialNo, - "db_file": certificate.DBFile, - "db_name": certificate.DBName, - "db_status": certificate.DBStatus, \ No newline at end of file diff --git a/x-pack/metricbeat/module/panos/certificates/types.go b/x-pack/metricbeat/module/panos/certificates/types.go deleted file mode 100644 index a06075f2630..00000000000 --- a/x-pack/metricbeat/module/panos/certificates/types.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package certificates - -type Response struct { - Status string `xml:"status,attr"` - Result string `xml:"result"` -} - -type Certificate struct { - CertName string - Issuer string - IssuerSubjectHash string - IssuerKeyHash string - DBType string - DBExpDate string - DBRevDate string - DBSerialNo string - DBFile string - DBName string - DBStatus string -} diff --git a/x-pack/metricbeat/module/panos/client.go b/x-pack/metricbeat/module/panos/client.go new file mode 100644 index 00000000000..a781b998716 --- /dev/null +++ b/x-pack/metricbeat/module/panos/client.go @@ -0,0 +1,45 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package panos + +import ( + "flag" + + "github.com/PaloAltoNetworks/pango" +) + +// PanosClient interface with an Op function +type PanosClient interface { + Op(req interface{}, vsys string, extras interface{}, ans interface{}) ([]byte, error) +} + +type PanosFirewallClient struct { + pango.Firewall +} + +type PanosTestClient struct { +} + +// Op is a mock function for testing that returns sample XML output based on the initial req parameter +// XML output is stored in the testdata directory, one file per query string +func (c *PanosTestClient) Op(req interface{}, vsys string, extras, ans interface{}) ([]byte, error) { + return nil, nil +} + +func GetPanosClient(config *Config) (PanosClient, error) { + // If running tests, return a test client + if flag.Lookup("test.v") != nil { + return &PanosTestClient{}, nil + } + + firewall := pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + err := firewall.Initialize() + if err != nil { + return nil, err + } + // Instantiate PanosFirewallClient + return &PanosFirewallClient{Firewall: firewall}, nil + +} diff --git a/x-pack/metricbeat/module/panos/config.go b/x-pack/metricbeat/module/panos/config.go new file mode 100644 index 00000000000..1bf01ca12b2 --- /dev/null +++ b/x-pack/metricbeat/module/panos/config.go @@ -0,0 +1,35 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package panos + +import ( + "errors" + + "github.com/elastic/beats/v7/metricbeat/mb" +) + +const ( + ModuleName = "panos" +) + +type Config struct { + HostIp string `config:"host_ip"` + ApiKey string `config:"apiKey"` + DebugMode string `config:"apiDebugMode"` +} + +func NewConfig(base mb.BaseMetricSet) (*Config, error) { + config := Config{} + if err := base.Module().UnpackConfig(&config); err != nil { + return nil, err + } + + if (config.HostIp == "") || (config.ApiKey == "") { + return nil, errors.New("host_ip and apiKey must be set ") + } + + return &config, nil + +} diff --git a/x-pack/metricbeat/module/panos/doc.go b/x-pack/metricbeat/module/panos/doc.go index 10f82619674..af2af1298ea 100644 --- a/x-pack/metricbeat/module/panos/doc.go +++ b/x-pack/metricbeat/module/panos/doc.go @@ -1,2 +1,6 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + // Package panos is a Metricbeat module that contains MetricSets. package panos diff --git a/x-pack/metricbeat/module/panos/fans/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/fans/_meta/docs.asciidoc deleted file mode 100644 index 723d4d9db76..00000000000 --- a/x-pack/metricbeat/module/panos/fans/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the fans metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/fans/_meta/fields.yml b/x-pack/metricbeat/module/panos/fans/_meta/fields.yml deleted file mode 100644 index c80aa2dbd26..00000000000 --- a/x-pack/metricbeat/module/panos/fans/_meta/fields.yml +++ /dev/null @@ -1,30 +0,0 @@ -- name: fans - type: group - release: beta - description: > - fans - fields: - - name: slot_number - type: integer - description: > - The number of the hardware slot - - - name: description - type: keyword - description: > - The description of the fan - - - name: alarm - type: boollean - description: > - Is there an alarm status of the fan - - - name: rpm - type: integer - description: > - The speed of the fan in RPM - - - name: min_rpm - type: integer - description: > - The minimum speed of the fan in RPM diff --git a/x-pack/metricbeat/module/panos/fans/types.go b/x-pack/metricbeat/module/panos/fans/types.go deleted file mode 100644 index 172d6865256..00000000000 --- a/x-pack/metricbeat/module/panos/fans/types.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package fans - -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Fan Fan `xml:"fan"` -} - -type Fan struct { - Slots []Slot `xml:",any"` -} - -type Slot struct { - Entries []Entry `xml:"entry"` -} - -type Entry struct { - Slot int `xml:"slot"` - Description string `xml:"description"` - Alarm string `xml:"alarm"` - RPMs int `xml:"RPMs"` - Min int `xml:"min"` -} diff --git a/x-pack/metricbeat/module/panos/fields.go b/x-pack/metricbeat/module/panos/fields.go index 8cc9f7e3e81..f37a88966ce 100644 --- a/x-pack/metricbeat/module/panos/fields.go +++ b/x-pack/metricbeat/module/panos/fields.go @@ -19,5 +19,5 @@ func init() { // AssetPanos returns asset data. // This is the base64 encoded zlib format compressed contents of module/panos. func AssetPanos() string { - return "eJzMlU1uwyAQhfc+xSj7XIBFdz1HNMHPLgoGBGOlvn2VuD8uJu2KltnZI39vvpEFR7pgURTY+dQRiRELRYf786EjirDgBEVnCHdEPZKOJojxTtFTR0TrtzT5frboiAYD2yd1bx3J8YQv/K1kCVA0Rj+H9zcF5nfMFnUewykAMX12Sshb5aN/VDFurRI8H2Q7DF55Cnfrba3jXLBcfeyz3g/ht3pegWvozl0jihmMZkEV/Qf8hjYwsKtinnFbMjYWaUmCqYp3id6Q/Wj9mW2IXqDllJCS8XX+gF+T2t2KsPzFSrKYhvbxwifjBHFgXedgfBTQ0A6s0XCpjn6B3ZK5H41mW0V8h27IO/grYg3rHNyQc72bsOVbUDAFRJY5ooZ6Gd+S/+wcbJWjbY/+R++3AAAA//8yVGcw" + return "eJzMl0uPmzAQx+/5FKO9b6Q97IVDpapqT23VQ3OOBjwkVsC2/EhKP31lnCeYRwmo9W0X5ff7D7bH5hUOVCWgUEizArDcFpTAS/33ywpAU0FoKIGULK4AGJlMc2W5FAl8WAFA+C2UkrmCVgA5p4KZpH70CgJLuuH9sJWiBHZaOnX+T4T5iLlHcWFJ55iRuT6KMf1oZr+MqC+MKL0Z5T4O/cJS1XXfj5DnQNVJatZ41mP343MABmmrei2d5WK3ROlt9H9Ut6mMpXKJslvkvqqdsrykNcPKRCv3y2dH+u8q39RQ4AJa3IZ3L52Oiye98pu4Db6aDeltJp2w8xX83ZUpaZB5TY97C4lsi0fSuKP1WxmV54XEZqwB9VeJDM5YX/gblFw4S8MZ3hfL8H7OMOZFLJfirT+GRXMwaystFvMthJ8eB+K6HGpJj147IR5b1JMBbivxjB6MYAoitVCGC3s4hJVKUXO3z5MhoAcj/JZlyuPt/8kEgdwTIFNu7RvHXDvh048NOOO3QVrVHQmUlhkZ07EVvL91asyXIKBHZBA8i0/AswmuajhxuwcEJQ23/EjglXDEwsUbpk/FWcetYGIqzwN/TnUaT8jjh9NEo+f1G/d8Tt8eNTuhpnD51E7ZoXW35R3H8cQERuZ2dAJLHUfAVLkHdr/vkkqpq56TZ4I2nDuB3CfNNc22lr9oohFKZzr6+gTlxhAboUxdnvtLHmb72ar9VqN9N2WQSw3BYQAFg7boess/oVpipj0XjMKsRzv7XI+Rzj7bY6R4RF5gOl+b/ngBxvQX9VGJJT7fHrH/8Iv1TwAAAP//L81TLA==" } diff --git a/x-pack/metricbeat/module/panos/filesystem/_meta/data.json b/x-pack/metricbeat/module/panos/filesystem/_meta/data.json deleted file mode 100644 index 7ec1ca25f3d..00000000000 --- a/x-pack/metricbeat/module/panos/filesystem/_meta/data.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "@timestamp":"2016-05-23T08:05:34.853Z", - "beat":{ - "hostname":"beathost", - "name":"beathost" - }, - "metricset":{ - "host":"localhost", - "module":"panos", - "name":"filesystem", - "rtt":44269 - }, - "panos":{ - "filesystem":{ - "example": "filesystem" - } - }, - "type":"metricsets" -} diff --git a/x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc deleted file mode 100644 index ce37e1eeefc..00000000000 --- a/x-pack/metricbeat/module/panos/filesystem/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the filesystem metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml b/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml deleted file mode 100644 index 9441e1dc359..00000000000 --- a/x-pack/metricbeat/module/panos/filesystem/_meta/fields.yml +++ /dev/null @@ -1,35 +0,0 @@ -- name: filesystem - type: group - release: beta - description: > - filesystem - fields: - - name: name - type: keyword - description: > - Filesystem name - - - name: size - type: keyword - description: > - Size, including units, e,g 9.5G. - - - name: used - type: keyword - description: > - Amount used, including units, e.g. 4.0G - - - name: available - type: keyword - description: > - Disk space available, including units, e.g. 5.5G - - - name: use_percent - type: keyword - description: > - Percent of filesystem used - - - name: mounted - type: keyword - description: > - Filesystem mount point diff --git a/x-pack/metricbeat/module/panos/filesystem/filesystem.go b/x-pack/metricbeat/module/panos/filesystem/filesystem.go deleted file mode 100644 index 7ef4b1e9949..00000000000 --- a/x-pack/metricbeat/module/panos/filesystem/filesystem.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package filesystem - -import ( - "encoding/xml" - "strings" - "time" - - "github.com/PaloAltoNetworks/pango" - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" -) - -const ( - metricsetName = "filesystem" - vsys = "" - query = "" -) - -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - config panos.Config - logger *logp.Logger - client *pango.Firewall -} - -// New creates a new instance of the MetricSet. New is responsible for unpacking -// any MetricSet specific configuration options if there are any. -func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos licenses metricset is beta.") - - config := panos.Config{} - logger := logp.NewLogger(base.FullyQualifiedName()) - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - logger.Debugf("panos_licenses metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - - return &MetricSet{ - BaseMetricSet: base, - config: config, - logger: logger, - client: client, - }, nil -} - -// Fetch method implements the data gathering and data conversion to the right -// format. It publishes the event which is then forwarded to the output. In case -// of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - log.Infof("panos_licenses.Fetch initialized client") - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - log.Error("Error: %s", err) - return err - } - - filesystems := getFilesystems(response.Result.Data) - events := getEvents(m, filesystems) - - for _, event := range events { - report.Event(event) - } - return nil -} - -func getFilesystems(input string) []Filesystem { - lines := strings.Split(input, "\n") - filesystems := make([]Filesystem, 0) - - for _, line := range lines[1:] { - fields := strings.Fields(line) - if len(fields) == 6 { - filesystem := Filesystem{ - Name: fields[0], - Size: fields[1], - Used: fields[2], - Avail: fields[3], - UsePerc: fields[4], - Mounted: fields[5], - } - filesystems = append(filesystems, filesystem) - } - } - return filesystems -} - -func getEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { - events := make([]mb.Event, 0, len(filesystems)) - - currentTime := time.Now() - - for _, filesystem := range filesystems { - event := mb.Event{MetricSetFields: mapstr.M{ - "name": filesystem.Name, - "size": filesystem.Size, - "used": filesystem.Used, - "available": filesystem.Avail, - "use_percent": filesystem.UsePerc, - "mounted": filesystem.Mounted, - }} - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - - events = append(events, event) - } - - return events - -} diff --git a/x-pack/metricbeat/module/panos/filesystem/types.go b/x-pack/metricbeat/module/panos/filesystem/types.go deleted file mode 100644 index e37c95ac8ef..00000000000 --- a/x-pack/metricbeat/module/panos/filesystem/types.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package filesystem - -import "encoding/xml" - -type Response struct { - XMLName xml.Name `xml:"response"` - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Data string `xml:",cdata"` -} - -type Filesystem struct { - Name string - Size string - Used string - Avail string - UsePerc string - Mounted string -} diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/data.json b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/data.json deleted file mode 100644 index 928bc1fda78..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/data.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "@timestamp":"2016-05-23T08:05:34.853Z", - "beat":{ - "hostname":"beathost", - "name":"beathost" - }, - "metricset":{ - "host":"localhost", - "module":"panos", - "name":"globalprotect_sessions", - "rtt":44269 - }, - "panos":{ - "globalprotect_sessions":{ - "example": "globalprotect_sessions" - } - }, - "type":"metricsets" -} diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/docs.asciidoc deleted file mode 100644 index d0150573a20..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the globalprotect_sessions metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml b/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml deleted file mode 100644 index d1d0086533e..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_sessions/_meta/fields.yml +++ /dev/null @@ -1,77 +0,0 @@ -- name: globalprotect_sessions - type: group - release: beta - description: globalprotect_sessions - fields: - - name: domain - type: keyword - description: Domain field - - name: is_local - type: keyword - description: Is Local field - - name: username - type: keyword - description: Username field - - name: primary_username - type: keyword - description: Primary Username field - - name: region_for_config - type: keyword - description: Region for Config field - - name: source_region - type: keyword - description: Source Region field - - name: computer - type: keyword - description: Computer field - - name: client - type: keyword - description: Client field - - name: vpn_type - type: keyword - description: VPN Type field - - name: host_id - type: keyword - description: Host ID field - - name: app_version - type: keyword - description: App Version field - - name: virtual_ip - type: keyword - description: Virtual IP field - - name: virtual_ipv6 - type: keyword - description: Virtual IPv6 field - - name: public_ip - type: keyword - description: Public IP field - - name: public_ipv6 - type: keyword - description: Public IPv6 field - - name: tunnel_type - type: keyword - description: Tunnel Type field - - name: public_connection_ipv6 - type: keyword - description: Public Connection IPv6 field - - name: client_ip - type: keyword - description: Client IP field - - name: login_time - type: keyword - description: Login Time field - - name: login_time_utc - type: keyword - description: Login Time UTC field - - name: lifetime - type: keyword - description: Lifetime field - - name: request_login - type: keyword - description: Request Login field - - name: request_get_config - type: keyword - description: Request Get Config field - - name: request_sslvpn_connect - type: keyword - description: Request SSLVPN Connect field diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go b/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go deleted file mode 100644 index 077950e40e2..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_sessions/globalprotect_sessions.go +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package globalprotect_sessions - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" -) - -const ( - metricsetName = "globalprotect_sessions" - vsys = "" - query = "" -) - -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - config panos.Config - logger *logp.Logger - client *pango.Firewall -} - -// New creates a new instance of the MetricSet. New is responsible for unpacking -// any MetricSet specific configuration options if there are any. -func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos globalprotect_sessions metricset is beta.") - - config := panos.Config{} - logger := logp.NewLogger(base.FullyQualifiedName()) - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - logger.Debugf("panos_licenses metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - - return &MetricSet{ - BaseMetricSet: base, - config: config, - logger: logger, - client: client, - }, nil -} - -// Fetch method implements the data gathering and data conversion to the right -// format. It publishes the event which is then forwarded to the output. In case -// of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - log.Infof("panos_licenses.Fetch initialized client") - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - log.Error("Error: %s", err) - return err - } - - events := getEvents(m, response.Result.Sessions) - - for _, event := range events { - report.Event(event) - } - - return nil -} - -func getEvents(m *MetricSet, sessions []Session) []mb.Event { - events := make([]mb.Event, 0, len(sessions)) - - currentTime := time.Now() - - for _, session := range sessions { - event := mb.Event{MetricSetFields: mapstr.M{ - "domain": session.Domain, - "is_local": session.IsLocal, - "username": session.Username, - "primary_username": session.PrimaryUsername, - "region_for_config": session.RegionForConfig, - "source_region": session.SourceRegion, - "computer": session.Computer, - "client": session.Client, - "vpn_type": session.VPNType, - "host_id": session.HostID, - "app_version": session.AppVersion, - "virtual_ip": session.VirtualIP, - "virtual_ipv6": session.VirtualIPv6, - "public_ip": session.PublicIP, - "public_ipv6": session.PublicIPv6, - "tunnel_type": session.TunnelType, - "public_connection_ipv6": session.PublicConnectionIPv6, - "client_ip": session.ClientIP, - "login_time": session.LoginTime, - "login_time_utc": session.LoginTimeUTC, - "lifetime": session.Lifetime, - "request_login": session.RequestLogin, - "request_get_config": session.RequestGetConfig, - "request_sslvpn_connect": session.RequestSSLVPNConnect, - }} - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - - events = append(events, event) - } - - return events -} diff --git a/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go b/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go deleted file mode 100644 index 635cd77c0b0..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_sessions/types.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package globalprotect_sessions - -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Sessions []Session `xml:"entry"` -} - -type Session struct { - Domain string `xml:"domain"` - IsLocal string `xml:"islocal"` - Username string `xml:"username"` - PrimaryUsername string `xml:"primary-username"` - RegionForConfig string `xml:"region-for-config"` - SourceRegion string `xml:"source-region"` - Computer string `xml:"computer"` - Client string `xml:"client"` - VPNType string `xml:"vpn-type"` - HostID string `xml:"host-id"` - AppVersion string `xml:"app-version"` - VirtualIP string `xml:"virtual-ip"` - VirtualIPv6 string `xml:"virtual-ipv6"` - PublicIP string `xml:"public-ip"` - PublicIPv6 string `xml:"public-ipv6"` - TunnelType string `xml:"tunnel-type"` - PublicConnectionIPv6 string `xml:"public-connection-ipv6"` - ClientIP string `xml:"client-ip"` - LoginTime string `xml:"login-time"` - LoginTimeUTC string `xml:"login-time-utc"` - Lifetime string `xml:"lifetime"` - RequestLogin string `xml:"request-login"` - RequestGetConfig string `xml:"request-getconfig"` - RequestSSLVPNConnect string `xml:"request-sslvpnconnect"` -} diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/data.json b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/data.json deleted file mode 100644 index ad493994cec..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/data.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "@timestamp":"2016-05-23T08:05:34.853Z", - "beat":{ - "hostname":"beathost", - "name":"beathost" - }, - "metricset":{ - "host":"localhost", - "module":"panos", - "name":"globalprotect_stats", - "rtt":44269 - }, - "panos":{ - "globalprotect_stats":{ - "example": "globalprotect_stats" - } - }, - "type":"metricsets" -} diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/docs.asciidoc deleted file mode 100644 index 550ca29c6e4..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the globalprotect_stats metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml b/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml deleted file mode 100644 index 4c73364fb49..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_stats/_meta/fields.yml +++ /dev/null @@ -1,27 +0,0 @@ -- name: globalprotect_stats - type: group - release: beta - description: > - globalprotect_stats - fields: - - name: gateway.name - type: keyword - description: > - Name of the GlobalProtect gateway - - name: gateway.current_users - type: integer - description: > - Number of current sessions on the gateway - - name: gateway.previous_users - type: integer - description: > - Number of previous sessions on the gateway - - name: total_current_users - type: integer - description: > - Total current users across all gateways - - name: total_previous_users - type: integer - description: > - Total previous users across all gateways - diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go b/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go deleted file mode 100644 index 694bb0ba178..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_stats/globalprotect_stats.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package globalprotect_stats - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" -) - -const ( - metricsetName = "globalprotect_stats" - vsys = "" - query = "" -) - -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - config panos.Config - logger *logp.Logger - client *pango.Firewall -} - -// New creates a new instance of the MetricSet. New is responsible for unpacking -// any MetricSet specific configuration options if there are any. -func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos globalprotect_stats metricset is beta.") - - config := panos.Config{} - logger := logp.NewLogger(base.FullyQualifiedName()) - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - logger.Debugf("panos_licenses metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - - return &MetricSet{ - BaseMetricSet: base, - config: config, - logger: logger, - client: client, - }, nil -} - -// Fetch method implements the data gathering and data conversion to the right -// format. It publishes the event which is then forwarded to the output. In case -// of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - log.Infof("panos_licenses.Fetch initialized client") - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - log.Error("Error: %s", err) - return err - } - - events := getEvents(m, response) - - for _, event := range events { - report.Event(event) - } - - return nil -} - -func getEvents(m *MetricSet, response Response) []mb.Event { - events := make([]mb.Event, 0, len(response.Result.Gateways)) - - currentTime := time.Now() - totalCurrent := response.Result.TotalCurrentUsers - totalPrevious := response.Result.TotalPreviousUsers - - for _, gateway := range response.Result.Gateways { - event := mb.Event{MetricSetFields: mapstr.M{ - "gateway.name": gateway.Name, - "gateway.current_users": gateway.CurrentUsers, - "gateway.previous_users": gateway.PreviousUsers, - "total_current_users": totalCurrent, - "total_previous_users": totalPrevious, - }} - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - - events = append(events, event) - } - - return events -} diff --git a/x-pack/metricbeat/module/panos/globalprotect_stats/types.go b/x-pack/metricbeat/module/panos/globalprotect_stats/types.go deleted file mode 100644 index 21f254389c0..00000000000 --- a/x-pack/metricbeat/module/panos/globalprotect_stats/types.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package globalprotect_stats - -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Gateways []Gateway `xml:"Gateway"` - TotalCurrentUsers int `xml:"TotalCurrentUsers"` - TotalPreviousUsers int `xml:"TotalPreviousUsers"` -} - -type Gateway struct { - Name string `xml:"name"` - CurrentUsers int `xml:"CurrentUsers"` - PreviousUsers int `xml:"PreviousUsers"` -} diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/data.json b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/data.json deleted file mode 100644 index a3db28e1f82..00000000000 --- a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/data.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "@timestamp":"2016-05-23T08:05:34.853Z", - "beat":{ - "hostname":"beathost", - "name":"beathost" - }, - "metricset":{ - "host":"localhost", - "module":"panos", - "name":"ha_interfaces", - "rtt":44269 - }, - "panos":{ - "ha_interfaces":{ - "example": "ha_interfaces" - } - }, - "type":"metricsets" -} diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/docs.asciidoc deleted file mode 100644 index e172b17e780..00000000000 --- a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the ha_interfaces metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml deleted file mode 100644 index 2f85c920487..00000000000 --- a/x-pack/metricbeat/module/panos/ha_interfaces/_meta/fields.yml +++ /dev/null @@ -1,167 +0,0 @@ -- name: ha_interfaces - type: group - release: beta - description: ha_interfaces - fields: - - name: enabled - type: keyword - description: Enabled field - - name: mode - type: keyword - description: Mode field - - name: running_sync - type: keyword - description: Running sync field - - name: running_sync_enabled - type: keyword - description: Running sync enabled field - - name: local_info.version - type: keyword - description: Local info version field - - name: local_info.state - type: keyword - description: Local info state field - - name: local_info.state_duration - type: integer - description: Local info state duration field - - name: local_info.mgmt_ip - type: ip - description: Local info management IP field - - name: local_info.preemptive - type: keyword - description: Local info preemptive field - - name: local_info.mode - type: keyword - description: Local info mode field - - name: local_info.platform_model - type: keyword - description: Local info platform model field - - name: local_info.state_sync - type: keyword - description: Local info state sync field - - name: local_info.state_sync_type - type: keyword - description: Local info state sync type field - - name: local_info.ha1_ipaddr - type: ip - description: Local info HA1 IP address field - - name: local_info.ha1_macaddr - type: keyword - description: Local info HA1 MAC address field - - name: local_info.ha1_port - type: keyword - description: Local info HA1 port field - - name: local_info.ha1_backup_ipaddr - type: ip - description: Local info HA1 backup IP address field - - name: local_info.ha1_backup_macaddr - type: keyword - description: Local info HA1 backup MAC address field - - name: local_info.ha1_backup_port - type: keyword - description: Local info HA1 backup port field - - name: local_info.ha1_backup_gateway - type: keyword - description: Local info HA1 backup gateway field - - name: local_info.ha2_ipaddr - type: keyword - description: Local info HA2 IP address field - - name: local_info.ha2_macaddr - type: keyword - description: Local info HA2 MAC address field - - name: local_info.ha2_port - type: keyword - description: Local info HA2 port field - - name: local_info.build_rel - type: keyword - description: Local info build release field - - name: local_info.url_version - type: keyword - description: Local info URL version field - - name: local_info.app_version - type: keyword - description: Local info app version field - - name: local_info.iot_version - type: keyword - description: Local info IoT version field - - name: local_info.av_version - type: keyword - description: Local info AV version field - - name: local_info.threat_version - type: keyword - description: Local info threat version field - - name: local_info.vpn_client_version - type: keyword - description: Local info VPN client version field - - name: local_info.gp_client_version - type: keyword - description: Local info GP client version field - - name: peer_info.conn_status - type: keyword - description: Peer info connection status field - - name: peer_info.state - type: keyword - description: Peer info state field - - name: peer_info.state_duration - type: integer - description: Peer info state duration field - - name: peer_info.mgmt_ip - type: ip - description: Peer info management IP field - - name: peer_info.preemptive - type: keyword - description: Peer info preemptive field - - name: peer_info.mode - type: keyword - description: Peer info mode field - - name: peer_info.platform_model - type: keyword - description: Peer info platform model field - - name: peer_info.priority - type: keyword - description: Peer info priority field - - name: peer_info.ha1_ipaddr - type: ip - description: Peer info HA1 IP address field - - name: peer_info.ha1_macaddr - type: keyword - description: Peer info HA1 MAC address field - - name: peer_info.ha1_backup_ipaddr - type: keyword - description: Peer info HA1 backup IP address field - - name: peer_info.ha1_backup_macaddr - type: keyword - description: Peer info HA1 backup MAC address field - - name: peer_info.ha2_ipaddr - type: ip - description: Peer info HA2 IP address field - - name: peer_info.ha2_macaddr - type: keyword - description: Peer info HA2 MAC address field - - name: peer_info.conn_ha1.status - type: keyword - description: Peer info HA1 connection status field - - name: peer_info.conn_ha1.primary - type: keyword - description: Peer info HA1 connection primary field - - name: peer_info.conn_ha1.description - type: keyword - description: Peer info HA1 connection description field - - name: peer_info.conn_ha2.status - type: keyword - description: Peer info HA2 connection status field - - name: peer_info.conn_ha2.primary - type: keyword - description: Peer info HA2 connection primary field - - name: peer_info.conn_ha2.description - type: keyword - description: Peer info HA2 connection description field - - name: peer_info.conn_ha1_backup.status - type: keyword - description: Peer info HA1 backup connection status field - - name: peer_info.conn_ha1_backup.description - type: keyword - description: Peer info HA1 backup connection description field - - name: link_monitoring.enabled - type: keyword - description: Link monitoring enabled field diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go deleted file mode 100644 index f710f5ffb85..00000000000 --- a/x-pack/metricbeat/module/panos/ha_interfaces/ha_interfaces.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package ha_interfaces - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" -) - -const ( - metricsetName = "ha_interfaces" - vsys = "" - query = "" -) - -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - config panos.Config - logger *logp.Logger - client *pango.Firewall -} - -// New creates a new instance of the MetricSet. New is responsible for unpacking -// any MetricSet specific configuration options if there are any. -func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos ha_interfaces metricset is beta.") - - config := panos.Config{} - logger := logp.NewLogger(base.FullyQualifiedName()) - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - logger.Debugf("panos_ha_interfaces metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - - return &MetricSet{ - BaseMetricSet: base, - config: config, - logger: logger, - client: client, - }, nil -} - -// Fetch method implements the data gathering and data conversion to the right -// format. It publishes the event which is then forwarded to the output. In case -// of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - log.Debug("panos_ha_interfaces.Fetch initialized client") - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - log.Error("Error: %s", err) - return err - } - - events := getEvents(m, response.Result) - for _, event := range events { - report.Event(event) - } - - return nil -} - -func getEvents(m *MetricSet, input Result) []mb.Event { - events := make([]mb.Event, 0, len(input.Group.LinkMonitoring.Groups)+1) - group := input.Group - - groupEvent := makeGroupEvent(m, input) - events = append(events, *groupEvent) - linkMonitorEvents := makeLinkMonitoringEvents(m, group.LinkMonitoring) - events = append(events, linkMonitorEvents...) - - return events -} - -func makeGroupEvent(m *MetricSet, input Result) *mb.Event { - group := input.Group - currentTime := time.Now() - event := mb.Event{MetricSetFields: mapstr.M{ - "enabled": input.Enabled, - "mode": group.Mode, - "running_sync": group.RunningSync, - "running_sync_enabled": group.RunningSyncEnabled, - "local_info.version": group.LocalInfo.Version, - "local_info.state": group.LocalInfo.State, - "local_info.state_duration": group.LocalInfo.StateDuration, - "local_info.mgmt_ip": group.LocalInfo.MgmtIP, - "local_info.preemptive": group.LocalInfo.Preemptive, - "local_info.mode": group.LocalInfo.Mode, - "local_info.platform_model": group.LocalInfo.PlatformModel, - "local_info.state_sync": group.LocalInfo.StateSync, - "local_info.state_sync_type": group.LocalInfo.StateSyncType, - "local_info.ha1_ipaddr": group.LocalInfo.HA1IPAddr, - "local_info.ha1_macaddr": group.LocalInfo.HA1MACAddr, - "local_info.ha1_port": group.LocalInfo.HA1Port, - "local_info.ha1_backup_ipaddr": group.LocalInfo.HA1BackupIPAddr, - "local_info.ha1_backup_macaddr": group.LocalInfo.HA1BackupMACAddr, - "local_info.ha1_backup_port": group.LocalInfo.HA1BackupPort, - "local_info.ha1_backup_gateway": group.LocalInfo.HA1BackupGateway, - "local_info.ha2_ipaddr": group.LocalInfo.HA2IPAddr, - "local_info.ha2_macaddr": group.LocalInfo.HA2MACAddr, - "local_info.ha2_port": group.LocalInfo.HA2Port, - "local_info.build_rel": group.LocalInfo.BuildRel, - "local_info.url_version": group.LocalInfo.URLVersion, - "local_info.app_version": group.LocalInfo.AppVersion, - "local_info.iot_version": group.LocalInfo.IoTVersion, - "local_info.av_version": group.LocalInfo.AVVersion, - "local_info.threat_version": group.LocalInfo.ThreatVersion, - "local_info.vpn_client_version": group.LocalInfo.VPNClientVersion, - "local_info.gp_client_version": group.LocalInfo.GPClientVersion, - "peer_info.conn_status": group.PeerInfo.ConnStatus, - "peer_info.state": group.PeerInfo.State, - "peer_info.state_duration": group.PeerInfo.StateDuration, - "peer_info.mgmt_ip": group.PeerInfo.MgmtIP, - "peer_info.preemptive": group.PeerInfo.Preemptive, - "peer_info.mode": group.PeerInfo.Mode, - "peer_info.platform_model": group.PeerInfo.PlatformModel, - "peer_info.priority": group.PeerInfo.Priority, - "peer_info.ha1_ipaddr": group.PeerInfo.HA1IPAddr, - "peer_info.ha1_macaddr": group.PeerInfo.HA1MACAddr, - "peer_info.ha1_backup_ipaddr": group.PeerInfo.HA1BackupIPAddr, - "peer_info.ha1_backup_macaddr": group.PeerInfo.HA1BackupMACAddr, - "peer_info.ha2_ipaddr": group.PeerInfo.HA2IPAddr, - "peer_info.ha2_macaddr": group.PeerInfo.HA2MACAddr, - "peer_info.conn_ha1.status": group.PeerInfo.ConnHA1.Status, - "peer_info.conn_ha1.primary": group.PeerInfo.ConnHA1.Primary, - "peer_info.conn_ha1.description": group.PeerInfo.ConnHA1.Desc, - "peer_info.conn_ha2.status": group.PeerInfo.ConnHA2.Status, - "peer_info.conn_ha2.primary": group.PeerInfo.ConnHA2.Primary, - "peer_info.conn_ha2.description": group.PeerInfo.ConnHA2.Desc, - "peer_info.conn_ha1_backup.status": group.PeerInfo.ConnHA1Backup.Status, - "peer_info.conn_ha1_backup.description": group.PeerInfo.ConnHA1Backup.Desc, - "link_monitoring.enabled": group.LinkMonitoring.Enabled, - }, - } - - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - - return &event -} - -func makeLinkMonitoringEvents(m *MetricSet, links LinkMonitoring) []mb.Event { - events := make([]mb.Event, 0, len(links.Groups)) - currentTime := time.Now() - var event mb.Event - for _, group := range links.Groups { - for _, interface_entry := range group.Interface { - event = mb.Event{MetricSetFields: mapstr.M{ - "link_monitoring.enabled": links.Enabled, - "link_monitoring.failure_condition": links.FailureCondition, - "link_monitoring.group.name": group.Name, - "link_monitoring.group.enabled": group.Enabled, - "link_monitoring.group.failure_condition": group.FailureCondition, - "link_monitoring.group.interface.name": interface_entry.Name, - "link_monitoring.group.interface.status": interface_entry.Status, - }} - } - - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - } - - events = append(events, event) - } - - return events -} diff --git a/x-pack/metricbeat/module/panos/licenses/_meta/data.json b/x-pack/metricbeat/module/panos/interfaces/_meta/data.json similarity index 76% rename from x-pack/metricbeat/module/panos/licenses/_meta/data.json rename to x-pack/metricbeat/module/panos/interfaces/_meta/data.json index eb1336ea518..4efd71bc73c 100644 --- a/x-pack/metricbeat/module/panos/licenses/_meta/data.json +++ b/x-pack/metricbeat/module/panos/interfaces/_meta/data.json @@ -7,12 +7,12 @@ "metricset":{ "host":"localhost", "module":"panos", - "name":"licenses", + "name":"interfaces", "rtt":44269 }, "panos":{ - "licenses":{ - "example": "licenses" + "interfaces":{ + "example": "interfaces" } }, "type":"metricsets" diff --git a/x-pack/metricbeat/module/panos/interfaces/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/interfaces/_meta/docs.asciidoc new file mode 100644 index 00000000000..fba7410ae86 --- /dev/null +++ b/x-pack/metricbeat/module/panos/interfaces/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the interfaces metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panos/interfaces/_meta/fields.yml new file mode 100644 index 00000000000..18f6505eaf2 --- /dev/null +++ b/x-pack/metricbeat/module/panos/interfaces/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: interfaces + type: group + release: beta + description: > + interfaces + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go new file mode 100644 index 00000000000..d105cd6b23a --- /dev/null +++ b/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go @@ -0,0 +1,149 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package interfaces + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getHAInterfaceEvents(m *MetricSet) ([]mb.Event, error) { + query := "" + var response HAResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatHAInterfaceEvents(m, response.Result) + + return events, nil + +} + +func formatHAInterfaceEvents(m *MetricSet, input HAResult) []mb.Event { + events := make([]mb.Event, 0, len(input.Group.LinkMonitoring.Groups)+1) + group := input.Group + + groupEvent := makeGroupEvent(m, input) + events = append(events, *groupEvent) + linkMonitorEvents := makeLinkMonitoringEvents(m, group.LinkMonitoring) + events = append(events, linkMonitorEvents...) + + return events +} + +func makeGroupEvent(m *MetricSet, input HAResult) *mb.Event { + group := input.Group + currentTime := time.Now() + event := mb.Event{MetricSetFields: mapstr.M{ + "ha.enabled": input.Enabled, + "ha.mode": group.Mode, + "ha.running_sync": group.RunningSync, + "ha.running_sync_enabled": group.RunningSyncEnabled, + "ha.local_info.version": group.LocalInfo.Version, + "ha.local_info.state": group.LocalInfo.State, + "ha.local_info.state_duration": group.LocalInfo.StateDuration, + "ha.local_info.mgmt_ip": group.LocalInfo.MgmtIP, + "ha.local_info.preemptive": group.LocalInfo.Preemptive, + "ha.local_info.mode": group.LocalInfo.Mode, + "ha.local_info.platform_model": group.LocalInfo.PlatformModel, + "ha.local_info.state_sync": group.LocalInfo.StateSync, + "ha.local_info.state_sync_type": group.LocalInfo.StateSyncType, + "ha.local_info.ha1_ipaddr": group.LocalInfo.HA1IPAddr, + "ha.local_info.ha1_macaddr": group.LocalInfo.HA1MACAddr, + "ha.local_info.ha1_port": group.LocalInfo.HA1Port, + "ha.local_info.ha1_backup_ipaddr": group.LocalInfo.HA1BackupIPAddr, + "ha.local_info.ha1_backup_macaddr": group.LocalInfo.HA1BackupMACAddr, + "ha.local_info.ha1_backup_port": group.LocalInfo.HA1BackupPort, + "ha.local_info.ha1_backup_gateway": group.LocalInfo.HA1BackupGateway, + "ha.local_info.ha2_ipaddr": group.LocalInfo.HA2IPAddr, + "ha.local_info.ha2_macaddr": group.LocalInfo.HA2MACAddr, + "ha.local_info.ha2_port": group.LocalInfo.HA2Port, + "ha.local_info.build_rel": group.LocalInfo.BuildRel, + "ha.local_info.url_version": group.LocalInfo.URLVersion, + "ha.local_info.app_version": group.LocalInfo.AppVersion, + "ha.local_info.iot_version": group.LocalInfo.IoTVersion, + "ha.local_info.av_version": group.LocalInfo.AVVersion, + "ha.local_info.threat_version": group.LocalInfo.ThreatVersion, + "ha.local_info.vpn_client_version": group.LocalInfo.VPNClientVersion, + "ha.local_info.gp_client_version": group.LocalInfo.GPClientVersion, + "ha.peer_info.conn_status": group.PeerInfo.ConnStatus, + "ha.peer_info.state": group.PeerInfo.State, + "ha.peer_info.state_duration": group.PeerInfo.StateDuration, + "ha.peer_info.mgmt_ip": group.PeerInfo.MgmtIP, + "ha.peer_info.preemptive": group.PeerInfo.Preemptive, + "ha.peer_info.mode": group.PeerInfo.Mode, + "ha.peer_info.platform_model": group.PeerInfo.PlatformModel, + "ha.peer_info.priority": group.PeerInfo.Priority, + "ha.peer_info.ha1_ipaddr": group.PeerInfo.HA1IPAddr, + "ha.peer_info.ha1_macaddr": group.PeerInfo.HA1MACAddr, + "ha.peer_info.ha1_backup_ipaddr": group.PeerInfo.HA1BackupIPAddr, + "ha.peer_info.ha1_backup_macaddr": group.PeerInfo.HA1BackupMACAddr, + "ha.peer_info.ha2_ipaddr": group.PeerInfo.HA2IPAddr, + "ha.peer_info.ha2_macaddr": group.PeerInfo.HA2MACAddr, + "ha.peer_info.conn_ha1.status": group.PeerInfo.ConnHA1.Status, + "ha.peer_info.conn_ha1.primary": group.PeerInfo.ConnHA1.Primary, + "ha.peer_info.conn_ha1.description": group.PeerInfo.ConnHA1.Desc, + "ha.peer_info.conn_ha2.status": group.PeerInfo.ConnHA2.Status, + "ha.peer_info.conn_ha2.primary": group.PeerInfo.ConnHA2.Primary, + "ha.peer_info.conn_ha2.description": group.PeerInfo.ConnHA2.Desc, + "ha.peer_info.conn_ha1_backup.status": group.PeerInfo.ConnHA1Backup.Status, + "ha.peer_info.conn_ha1_backup.description": group.PeerInfo.ConnHA1Backup.Desc, + "ha.link_monitoring.enabled": group.LinkMonitoring.Enabled, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }, + } + + return &event +} + +func makeLinkMonitoringEvents(m *MetricSet, links HALinkMonitoring) []mb.Event { + events := make([]mb.Event, 0, len(links.Groups)) + currentTime := time.Now() + var event mb.Event + for _, group := range links.Groups { + for _, interface_entry := range group.Interface { + event = mb.Event{MetricSetFields: mapstr.M{ + "ha.link_monitoring.enabled": links.Enabled, + "ha.llink_monitoring.failure_condition": links.FailureCondition, + "ha.llink_monitoring.group.name": group.Name, + "ha.llink_monitoring.group.enabled": group.Enabled, + "ha.llink_monitoring.group.failure_condition": group.FailureCondition, + "ha.llink_monitoring.group.interface.name": interface_entry.Name, + "ha.llink_monitoring.group.interface.status": interface_entry.Status, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }, + } + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/interfaces/ifnet_interfaces.go b/x-pack/metricbeat/module/panos/interfaces/ifnet_interfaces.go new file mode 100644 index 00000000000..525601352f3 --- /dev/null +++ b/x-pack/metricbeat/module/panos/interfaces/ifnet_interfaces.go @@ -0,0 +1,115 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package interfaces + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +// these types apply to phyiscal interfaces +var interfaceTypes = map[int]string{ + 0: "Ethernet interface", + 1: "Aggregate Ethernet (AE) interface", + 2: "High Availability (HA) interface", + 3: "VLAN interface", + 5: "Loopback interface", + 6: "Tunnel interface", + 10: "SD-WAN interface", +} + +func getIFNetInterfaceEvents(m *MetricSet) ([]mb.Event, error) { + query := "all" + var response InterfaceResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatIFInterfaceEvents(m, response.Result) + + return events, nil + +} + +func formatIFInterfaceEvents(m *MetricSet, input InterfaceResult) []mb.Event { + events := make([]mb.Event, 0, len(input.HW.Entries)+len(input.Ifnet.Entries)) + currentTime := time.Now() + + // First process the phyiscal interfaces + for _, entry := range input.HW.Entries { + iftype := interfaceTypes[entry.Type] + + var members []string + // If this is an aggregate interface, populate the members + if entry.Type == 1 { + members = entry.AEMember.Members + } + + event := mb.Event{MetricSetFields: mapstr.M{ + "name": entry.Name, + "id": entry.ID, + "type": iftype, + "mac": entry.MAC, + "speed": entry.Speed, + "duplex": entry.Duplex, + "state": entry.State, + "mode": entry.Mode, + "st": entry.ST, + "ae_member": members, + "logical": false, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }, + } + + events = append(events, event) + } + + // Now process the logical interfaces + for _, entry := range input.Ifnet.Entries { + event := mb.Event{MetricSetFields: mapstr.M{ + "name": entry.Name, + "id": entry.ID, + "tag": entry.Tag, + "vsys": entry.Vsys, + "zone": entry.Zone, + "fwd": entry.Fwd, + "ip": entry.IP_CIDR, + "addr": entry.Addr, + "dyn_addr": entry.DynAddr, + "addr6": entry.Addr6, + "logical": true, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + + events = append(events, event) + + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/ha_interfaces/type.go b/x-pack/metricbeat/module/panos/interfaces/interface_types.go similarity index 70% rename from x-pack/metricbeat/module/panos/ha_interfaces/type.go rename to x-pack/metricbeat/module/panos/interfaces/interface_types.go index 23432831c3f..abca8bafe63 100644 --- a/x-pack/metricbeat/module/panos/ha_interfaces/type.go +++ b/x-pack/metricbeat/module/panos/interfaces/interface_types.go @@ -2,34 +2,83 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package ha_interfaces +package interfaces -import ( - "encoding/xml" -) +import "encoding/xml" -type Response struct { +type InterfaceResponse struct { + XMLName xml.Name `xml:"response"` + Status string `xml:"status,attr"` + Result InterfaceResult `xml:"result"` +} + +type InterfaceResult struct { + HW HW `xml:"hw"` + Ifnet Ifnet `xml:"ifnet"` +} + +type HW struct { + Entries []HWInterfaceEntry `xml:"entry"` +} + +type HWInterfaceEntry struct { + Name string `xml:"name"` + ID int `xml:"id"` + Type int `xml:"type"` + MAC string `xml:"mac"` + Speed string `xml:"speed"` + Duplex string `xml:"duplex"` + State string `xml:"state"` + Mode string `xml:"mode"` + ST string `xml:"st"` + AEMember AEMember `xml:"ae_member"` +} + +type IFInterfaceEntry struct { + Name string `xml:"name"` + ID int `xml:"id"` + Tag int `xml:"tag"` + Vsys int `xml:"vsys"` + Zone string `xml:"zone"` + Fwd string `xml:"fwd"` + IP_CIDR string `xml:"ip"` + Addr string `xml:"addr"` + DynAddr string `xml:"dyn-addr"` + Addr6 string `xml:"addr6"` +} + +type AEMember struct { + Members []string `xml:"member"` +} + +type Ifnet struct { + Entries []IFInterfaceEntry `xml:"entry"` +} + +// HA Interfaces + +type HAResponse struct { XMLName xml.Name `xml:"response"` Status string `xml:"status,attr"` - Result Result `xml:"result"` + Result HAResult `xml:"result"` } -type Result struct { - Enabled string `xml:"enabled"` - Group Group `xml:"group"` +type HAResult struct { + Enabled string `xml:"enabled"` + Group HAGroup `xml:"group"` } -type Group struct { - Mode string `xml:"mode"` - LocalInfo LocalInfo `xml:"local-info"` - PeerInfo PeerInfo `xml:"peer-info"` - LinkMonitoring LinkMonitoring `xml:"link-monitoring"` - PathMonitoring PathMonitoring `xml:"path-monitoring"` - RunningSync string `xml:"running-sync"` - RunningSyncEnabled string `xml:"running-sync-enabled"` +type HAGroup struct { + Mode string `xml:"mode"` + LocalInfo HALocalInfo `xml:"local-info"` + PeerInfo HAPeerInfo `xml:"peer-info"` + LinkMonitoring HALinkMonitoring `xml:"link-monitoring"` + PathMonitoring HAPathMonitoring `xml:"path-monitoring"` + RunningSync string `xml:"running-sync"` + RunningSyncEnabled string `xml:"running-sync-enabled"` } -type LocalInfo struct { +type HALocalInfo struct { Version string `xml:"version"` State string `xml:"state"` StateDuration int `xml:"state-duration"` @@ -88,7 +137,7 @@ type ActivePassive struct { MonitorFailHolddown int `xml:"monitor-fail-holddown"` } -type PeerInfo struct { +type HAPeerInfo struct { ConnHA1 ConnHA1 `xml:"conn-ha1"` ConnHA1Backup ConnHA1Backup `xml:"conn-ha1-backup"` ConnHA2 ConnHA2 `xml:"conn-ha2"` @@ -140,25 +189,25 @@ type ConnHA2 struct { Status string `xml:"conn-status"` } -type LinkMonitoring struct { - Enabled string `xml:"enabled"` - FailureCondition string `xml:"failure-condition"` - Groups []GroupEntry `xml:"groups>entry"` +type HALinkMonitoring struct { + Enabled string `xml:"enabled"` + FailureCondition string `xml:"failure-condition"` + Groups []HAGroupEntry `xml:"groups>entry"` } -type GroupEntry struct { - Name string `xml:"name"` - Enabled string `xml:"enabled"` - FailureCondition string `xml:"failure-condition"` - Interface []InterfaceEntry `xml:"interface>entry"` +type HAGroupEntry struct { + Name string `xml:"name"` + Enabled string `xml:"enabled"` + FailureCondition string `xml:"failure-condition"` + Interface []HAInterfaceEntry `xml:"interface>entry"` } -type InterfaceEntry struct { +type HAInterfaceEntry struct { Name string `xml:"name"` Status string `xml:"status"` } -type PathMonitoring struct { +type HAPathMonitoring struct { Enabled string `xml:"enabled"` FailureCondition string `xml:"failure-condition"` VirtualWire string `xml:"virtual-wire"` diff --git a/x-pack/metricbeat/module/panos/fans/fans.go b/x-pack/metricbeat/module/panos/interfaces/interfaces.go similarity index 51% rename from x-pack/metricbeat/module/panos/fans/fans.go rename to x-pack/metricbeat/module/panos/interfaces/interfaces.go index a8fdbc4ad2e..a25501e1d8f 100644 --- a/x-pack/metricbeat/module/panos/fans/fans.go +++ b/x-pack/metricbeat/module/panos/interfaces/interfaces.go @@ -2,60 +2,59 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package fans +package interfaces import ( - "encoding/xml" - "time" + "errors" + "strings" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" ) const ( - metricsetName = "fans" + metricsetName = "interfaces" vsys = "" - query = "" ) -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - // MetricSet holds any configuration or state information. It must implement // the mb.MetricSet interface. And this is best achieved by embedding // mb.BaseMetricSet because it implements all of the required mb.MetricSet // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - config panos.Config + config *panos.Config logger *logp.Logger - client *pango.Firewall + client panos.PanosClient +} + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) } // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos fans metricset is beta.") + cfgwarn.Beta("The panos interfaces metricset is beta.") + + config, err := panos.NewConfig(base) + if err != nil { + return nil, err + } - config := panos.Config{} logger := logp.NewLogger(base.FullyQualifiedName()) - if err := base.Module().UnpackConfig(&config); err != nil { + //client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + client, err := panos.GetPanosClient(config) + if err != nil { return nil, err } - logger.Debugf("panos_power metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} return &MetricSet{ BaseMetricSet: base, @@ -69,62 +68,33 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response + // accumulate errs and report them all at the end so that we don't + // stop processing events if one of the fetches fails + var errs []string - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err + intefaceEvents, err := getIFNetInterfaceEvents(m) + if err != nil { + m.logger.Error("Error get IFInterface events: %s", err) + errs = append(errs, err.Error()) } - log.Infof("panos_licenses.Fetch initialized client") - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err + for _, event := range intefaceEvents { + report.Event(event) } - err = xml.Unmarshal(output, &response) + haEvents, err := getHAInterfaceEvents(m) if err != nil { - log.Error("Error: %s", err) - return err + m.logger.Error("Error get HAInterface events: %s", err) + errs = append(errs, err.Error()) } - events := getEvents(m, &response) - - for _, event := range events { + for _, event := range haEvents { report.Event(event) } - return nil -} - -func getEvents(m *MetricSet, response *Response) []mb.Event { - log := m.Logger() - events := make([]mb.Event, 0, len(response.Result.Fan.Slots)) - currentTime := time.Now() - var event mb.Event - for _, slot := range response.Result.Fan.Slots { - for _, entry := range slot.Entries { - log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) - event = mb.Event{MetricSetFields: mapstr.M{ - "slot_number": entry.Slot, - "description": entry.Description, - "alarm": entry.Alarm, - "rpm": entry.RPMs, - "min_rpm": entry.Min, - }} - } - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - events = append(events, event) + if len(errs) > 0 { + return errors.New(strings.Join(errs, "; ")) + } else { + return nil } - - return events } diff --git a/x-pack/metricbeat/module/panos/licenses/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/licenses/_meta/docs.asciidoc deleted file mode 100644 index dcf92265866..00000000000 --- a/x-pack/metricbeat/module/panos/licenses/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the licenses metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml b/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml deleted file mode 100644 index e8feed1cf4f..00000000000 --- a/x-pack/metricbeat/module/panos/licenses/_meta/fields.yml +++ /dev/null @@ -1,26 +0,0 @@ -- name: licenses - type: group - release: beta - description: licenses - fields: - - name: feature - type: keyword - description: Feature licensed - - name: description - type: text - description: Description field - - name: serial - type: keyword - description: Serial number of license - - name: issued - type: date - description: Issued date field - - name: expires - type: date - description: Expires date field - - name: expired - type: boolean - description: Expired field - - name: auth_code - type: keyword - description: Auth code field diff --git a/x-pack/metricbeat/module/panos/licenses/types.go b/x-pack/metricbeat/module/panos/licenses/types.go deleted file mode 100644 index ae74999f514..00000000000 --- a/x-pack/metricbeat/module/panos/licenses/types.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package licenses - -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Licenses []License `xml:"licenses>entry"` -} - -type License struct { - Feature string `xml:"feature"` - Description string `xml:"description"` - Serial string `xml:"serial"` - Issued string `xml:"issued"` - Expires string `xml:"expires"` - Expired string `xml:"expired"` - AuthCode string `xml:"authcode"` -} diff --git a/x-pack/metricbeat/module/panos/logical/_meta/data.json b/x-pack/metricbeat/module/panos/logical/_meta/data.json deleted file mode 100644 index a0fc6777cae..00000000000 --- a/x-pack/metricbeat/module/panos/logical/_meta/data.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "@timestamp":"2016-05-23T08:05:34.853Z", - "beat":{ - "hostname":"beathost", - "name":"beathost" - }, - "metricset":{ - "host":"localhost", - "module":"panos", - "name":"logical", - "rtt":44269 - }, - "panos":{ - "logical":{ - "example": "logical" - } - }, - "type":"metricsets" -} diff --git a/x-pack/metricbeat/module/panos/logical/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/logical/_meta/docs.asciidoc deleted file mode 100644 index 3ad0493e25b..00000000000 --- a/x-pack/metricbeat/module/panos/logical/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the logical metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/logical/_meta/fields.yml b/x-pack/metricbeat/module/panos/logical/_meta/fields.yml deleted file mode 100644 index f2c844620bb..00000000000 --- a/x-pack/metricbeat/module/panos/logical/_meta/fields.yml +++ /dev/null @@ -1,35 +0,0 @@ -- name: logical - type: group - release: beta - description: logical - fields: - - name: name - type: keyword - description: Name of logical interface - - name: id - type: keyword - description: ID of logical interface - - name: tag - type: keyword - description: Tag field - - name: vsys - type: keyword - description: Virtual system for this interface - - name: zone - type: keyword - description: Zone field - - name: fwd - type: keyword - description: Forward field - - name: ip - type: ip - description: IP field - - name: addr - type: keyword - description: Address field - - name: dyn_addr - type: keyword - description: Dynamic Address field - - name: addr6 - type: keyword - description: IPv6 Address field diff --git a/x-pack/metricbeat/module/panos/logical/logical.go b/x-pack/metricbeat/module/panos/logical/logical.go deleted file mode 100644 index 2aceea27e19..00000000000 --- a/x-pack/metricbeat/module/panos/logical/logical.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package logical - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" -) - -const ( - metricsetName = "logical" - vsys = "" - query = "logical" -) - -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - config panos.Config - logger *logp.Logger - client *pango.Firewall -} - -// New creates a new instance of the MetricSet. New is responsible for unpacking -// any MetricSet specific configuration options if there are any. -func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos logical metricset is beta.") - config := panos.Config{} - logger := logp.NewLogger(base.FullyQualifiedName()) - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - logger.Debugf("panos_licenses metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - - return &MetricSet{ - BaseMetricSet: base, - config: config, - logger: logger, - client: client, - }, nil -} - -// Fetch method implements the data gathering and data conversion to the right -// format. It publishes the event which is then forwarded to the output. In case -// of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - log.Infof("panos_licenses.Fetch initialized client") - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - log.Error("Error: %s", err) - return err - } - - events := getEvents(m, response.Result.Ifnet.LogicalInterfaces) - - for _, event := range events { - report.Event(event) - } - - return nil -} - -func getEvents(m *MetricSet, interfaces []LogicalInterface) []mb.Event { - events := make([]mb.Event, 0, len(interfaces)) - - currentTime := time.Now() - - for _, logicalInterface := range interfaces { - event := mb.Event{MetricSetFields: mapstr.M{ - "name": logicalInterface.Name, - "id": logicalInterface.ID, - "tag": logicalInterface.Tag, - "vsys": logicalInterface.Vsys, - "zone": logicalInterface.Zone, - "fwd": logicalInterface.Fwd, - "ip": logicalInterface.IP, - "addr": logicalInterface.Addr, - "dyn_addr": logicalInterface.DynAddr, - "addr6": logicalInterface.Addr6, - }} - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - - events = append(events, event) - } - - return events - -} diff --git a/x-pack/metricbeat/module/panos/logical/types.go b/x-pack/metricbeat/module/panos/logical/types.go deleted file mode 100644 index ba1f77d917e..00000000000 --- a/x-pack/metricbeat/module/panos/logical/types.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package logical - -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Ifnet Ifnet `xml:"ifnet"` -} - -type Ifnet struct { - LogicalInterfaces []LogicalInterface `xml:"entry"` -} - -type LogicalInterface struct { - Name string `xml:"name"` - ID int `xml:"id"` - Tag int `xml:"tag"` - Vsys int `xml:"vsys"` - Zone string `xml:"zone"` - Fwd string `xml:"fwd"` - IP string `xml:"ip"` - Addr string `xml:"addr"` - DynAddr string `xml:"dyn-addr"` - Addr6 string `xml:"addr6"` -} diff --git a/x-pack/metricbeat/module/panos/power/_meta/data.json b/x-pack/metricbeat/module/panos/power/_meta/data.json deleted file mode 100644 index 0c303cd35c2..00000000000 --- a/x-pack/metricbeat/module/panos/power/_meta/data.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "@timestamp":"2016-05-23T08:05:34.853Z", - "beat":{ - "hostname":"beathost", - "name":"beathost" - }, - "metricset":{ - "host":"localhost", - "module":"panos", - "name":"power", - "rtt":44269 - }, - "panos":{ - "power":{ - "example": "power" - } - }, - "type":"metricsets" -} diff --git a/x-pack/metricbeat/module/panos/power/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/power/_meta/docs.asciidoc deleted file mode 100644 index 3e3326a515f..00000000000 --- a/x-pack/metricbeat/module/panos/power/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the power metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/power/_meta/fields.yml b/x-pack/metricbeat/module/panos/power/_meta/fields.yml deleted file mode 100644 index 59dbae274af..00000000000 --- a/x-pack/metricbeat/module/panos/power/_meta/fields.yml +++ /dev/null @@ -1,23 +0,0 @@ -- name: power - type: group - release: beta - description: power - fields: - - name: slot_number - type: keyword - description: Slot number field - - name: description - type: text - description: Description field - - name: alarm - type: boolean - description: Indicates if alarm is active - - name: volts - type: float - description: Current Volts - - name: minimum_volts - type: float - description: Minimum volts recorded - - name: maximum_volts - type: float - description: Maximum volts recorded diff --git a/x-pack/metricbeat/module/panos/power/types.go b/x-pack/metricbeat/module/panos/power/types.go deleted file mode 100644 index 2edc14f5c1f..00000000000 --- a/x-pack/metricbeat/module/panos/power/types.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package power - -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Power Power `xml:"power"` -} - -type Power struct { - Slots []Slot `xml:",any"` -} - -type Slot struct { - Entries []Entry `xml:"entry"` -} - -type Entry struct { - Slot int `xml:"slot"` - Description string `xml:"description"` - Alarm bool `xml:"alarm"` - Volts float64 `xml:"Volts"` - MinimumVolts float64 `xml:"min"` - MaximumVolts float64 `xml:"max"` -} diff --git a/x-pack/metricbeat/module/panos/tunnels/_meta/data.json b/x-pack/metricbeat/module/panos/routing/_meta/data.json similarity index 77% rename from x-pack/metricbeat/module/panos/tunnels/_meta/data.json rename to x-pack/metricbeat/module/panos/routing/_meta/data.json index a7f7868192d..8bb0746b1e8 100644 --- a/x-pack/metricbeat/module/panos/tunnels/_meta/data.json +++ b/x-pack/metricbeat/module/panos/routing/_meta/data.json @@ -7,12 +7,12 @@ "metricset":{ "host":"localhost", "module":"panos", - "name":"tunnels", + "name":"routing", "rtt":44269 }, "panos":{ - "tunnels":{ - "example": "tunnels" + "routing":{ + "example": "routing" } }, "type":"metricsets" diff --git a/x-pack/metricbeat/module/panos/routing/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/routing/_meta/docs.asciidoc new file mode 100644 index 00000000000..bee51fd8b44 --- /dev/null +++ b/x-pack/metricbeat/module/panos/routing/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the routing metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/routing/_meta/fields.yml b/x-pack/metricbeat/module/panos/routing/_meta/fields.yml new file mode 100644 index 00000000000..9b001ae10e6 --- /dev/null +++ b/x-pack/metricbeat/module/panos/routing/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: routing + type: group + release: beta + description: > + routing + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/routing/bgp_peers.go b/x-pack/metricbeat/module/panos/routing/bgp_peers.go new file mode 100644 index 00000000000..c9c78be9779 --- /dev/null +++ b/x-pack/metricbeat/module/panos/routing/bgp_peers.go @@ -0,0 +1,97 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package routing + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getBGPEvents(m *MetricSet) ([]mb.Event, error) { + query := "" + var response BGPResponse + + // Initialize the client + // if err := m.client.Initialize(); err != nil { + // log.Error("Failed to initialize client: %s", err) + // return err + // } + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error calling API: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error unmarshalling: %s", err) + return nil, err + } + + events := formatBGPEvents(m, response.Result.Entries) + + return events, nil +} + +func formatBGPEvents(m *MetricSet, entries []BGPEntry) []mb.Event { + events := make([]mb.Event, 0, len(entries)) + currentTime := time.Now() + + for _, entry := range entries { + event := mb.Event{MetricSetFields: mapstr.M{ + "bgp_peer_name": entry.Peer, + "virtual_router": entry.Vr, + "bgp_peer_group": entry.PeerGroup, + "bgp_peer_router_id": entry.PeerRouterID, + "remote_as_asn": entry.RemoteAS, + "status": entry.Status, + "status_duration": entry.StatusDuration, + "password_set": entry.PasswordSet, + "passive": entry.Passive, + "multi_hop_ttl": entry.MultiHopTTL, + "peer_address": entry.PeerAddress, + "local_address": entry.LocalAddress, + "reflector_client": entry.ReflectorClient, + "same_confederation": entry.SameConfederation, + "aggregate_confed_as": entry.AggregateConfedAS, + "peering_type": entry.PeeringType, + "connect_retry_interval": entry.ConnectRetryInterval, + "open_delay": entry.OpenDelay, + "idle_hold": entry.IdleHold, + "prefix_limit": entry.PrefixLimit, + "holdtime": entry.Holdtime, + "holdtime_config": entry.HoldtimeConfig, + "keepalive": entry.Keepalive, + "keepalive_config": entry.KeepaliveConfig, + "msg_update_in": entry.MsgUpdateIn, + "msg_update_out": entry.MsgUpdateOut, + "msg_total_in": entry.MsgTotalIn, + "msg_total_out": entry.MsgTotalOut, + "last_update_age": entry.LastUpdateAge, + "last_error": entry.LastError, + "status_flap_counts": entry.StatusFlapCounts, + "established_counts": entry.EstablishedCounts, + "orf_entry_received": entry.ORFEntryReceived, + "nexthop_self": entry.NexthopSelf, + "nexthop_thirdparty": entry.NexthopThirdparty, + "nexthop_peer": entry.NexthopPeer, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/power/power.go b/x-pack/metricbeat/module/panos/routing/routing.go similarity index 50% rename from x-pack/metricbeat/module/panos/power/power.go rename to x-pack/metricbeat/module/panos/routing/routing.go index eb111943ad0..33e7659eef5 100644 --- a/x-pack/metricbeat/module/panos/power/power.go +++ b/x-pack/metricbeat/module/panos/routing/routing.go @@ -2,60 +2,58 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package power +package routing import ( - "encoding/xml" - "time" + "errors" + "strings" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" ) const ( - metricsetName = "power" + metricsetName = "routing" vsys = "" - query = "" ) -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - // MetricSet holds any configuration or state information. It must implement // the mb.MetricSet interface. And this is best achieved by embedding // mb.BaseMetricSet because it implements all of the required mb.MetricSet // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - config panos.Config + config *panos.Config logger *logp.Logger - client *pango.Firewall + client panos.PanosClient +} + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) } // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos power metricset is beta.") + cfgwarn.Beta("The panos routing metricset is beta.") + + config, err := panos.NewConfig(base) + if err != nil { + return nil, err + } - config := panos.Config{} logger := logp.NewLogger(base.FullyQualifiedName()) - if err := base.Module().UnpackConfig(&config); err != nil { + client, err := panos.GetPanosClient(config) + if err != nil { return nil, err } - logger.Debugf("panos_power metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} return &MetricSet{ BaseMetricSet: base, @@ -69,64 +67,23 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - log.Infof("panos_licenses.Fetch initialized client") + // accumulate errs and report them all at the end so that we don't + // stop processing events if one of the fetches fails + var errs []string - output, err := m.client.Op(query, vsys, nil, nil) + bgpEvents, err := getBGPEvents(m) if err != nil { - log.Error("Error: %s", err) - return err + m.logger.Error("Error get BGP events: %s", err) + errs = append(errs, err.Error()) } - err = xml.Unmarshal(output, &response) - if err != nil { - log.Error("Error: %s", err) - return err - } - - events := getEvents(m, &response) - - for _, event := range events { + for _, event := range bgpEvents { report.Event(event) } - return nil -} - -func getEvents(m *MetricSet, response *Response) []mb.Event { - log := m.Logger() - events := make([]mb.Event, 0, len(response.Result.Power.Slots)) - currentTime := time.Now() - var event mb.Event - for _, slot := range response.Result.Power.Slots { - for _, entry := range slot.Entries { - log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) - event = mb.Event{MetricSetFields: mapstr.M{ - - "slot_number": entry.Slot, - "description": entry.Description, - "alarm": entry.Alarm, - "volts": entry.Volts, - "minimum_volts": entry.MinimumVolts, - "maximum_volts": entry.MaximumVolts, - }} - } - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - events = append(events, event) + if len(errs) > 0 { + return errors.New(strings.Join(errs, "; ")) + } else { + return nil } - - return events } diff --git a/x-pack/metricbeat/module/panos/routing/routing_types.go b/x-pack/metricbeat/module/panos/routing/routing_types.go new file mode 100644 index 00000000000..1b39751edb8 --- /dev/null +++ b/x-pack/metricbeat/module/panos/routing/routing_types.go @@ -0,0 +1,83 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package routing + +type BGPResponse struct { + Status string `xml:"status,attr"` + Result BGPResult `xml:"result"` +} + +type BGPResult struct { + Entries []BGPEntry `xml:"entry"` +} + +type BGPEntry struct { + Peer string `xml:"peer,attr"` + Vr string `xml:"vr,attr"` + PeerGroup string `xml:"peer-group"` + PeerRouterID string `xml:"peer-router-id"` + RemoteAS int `xml:"remote-as"` + Status string `xml:"status"` + StatusDuration int `xml:"status-duration"` + PasswordSet string `xml:"password-set"` + Passive string `xml:"passive"` + MultiHopTTL int `xml:"multi-hop-ttl"` + PeerAddress string `xml:"peer-address"` + LocalAddress string `xml:"local-address"` + ReflectorClient string `xml:"reflector-client"` + SameConfederation string `xml:"same-confederation"` + AggregateConfedAS string `xml:"aggregate-confed-as"` + PeeringType string `xml:"peering-type"` + ConnectRetryInterval int `xml:"connect-retry-interval"` + OpenDelay int `xml:"open-delay"` + IdleHold int `xml:"idle-hold"` + PrefixLimit int `xml:"prefix-limit"` + Holdtime int `xml:"holdtime"` + HoldtimeConfig int `xml:"holdtime-config"` + Keepalive int `xml:"keepalive"` + KeepaliveConfig int `xml:"keepalive-config"` + MsgUpdateIn int `xml:"msg-update-in"` + MsgUpdateOut int `xml:"msg-update-out"` + MsgTotalIn int `xml:"msg-total-in"` + MsgTotalOut int `xml:"msg-total-out"` + LastUpdateAge int `xml:"last-update-age"` + LastError string `xml:"last-error"` + StatusFlapCounts int `xml:"status-flap-counts"` + EstablishedCounts int `xml:"established-counts"` + ORFEntryReceived int `xml:"ORF-entry-received"` + NexthopSelf string `xml:"nexthop-self"` + NexthopThirdparty string `xml:"nexthop-thirdparty"` + NexthopPeer string `xml:"nexthop-peer"` + Config BGPConfig `xml:"config"` + PeerCapability BGPPeerCapability `xml:"peer-capability"` + PrefixCounter BGPPrefixCounter `xml:"prefix-counter"` +} + +type BGPConfig struct { + RemovePrivateAS string `xml:"remove-private-as"` +} + +type BGPPeerCapability struct { + List []BGPCapability `xml:"list"` +} + +type BGPCapability struct { + Capability string `xml:"capability"` + Value string `xml:"value"` +} + +type BGPPrefixCounter struct { + Entries []BGPPrefixEntry `xml:"entry"` +} + +type BGPPrefixEntry struct { + AfiSafi string `xml:"afi-safi,attr"` + IncomingTotal int `xml:"incoming-total"` + IncomingAccepted int `xml:"incoming-accepted"` + IncomingRejected int `xml:"incoming-rejected"` + PolicyRejected int `xml:"policy-rejected"` + OutgoingTotal int `xml:"outgoing-total"` + OutgoingAdvertised int `xml:"outgoing-advertised"` +} diff --git a/x-pack/metricbeat/module/panos/system/_meta/fields.yml b/x-pack/metricbeat/module/panos/system/_meta/fields.yml index 1909871d474..018e44d5abc 100644 --- a/x-pack/metricbeat/module/panos/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/system/_meta/fields.yml @@ -93,7 +93,7 @@ description: > Used memory - name: memory.buffer_cache - type: keyflaotword + type: float description: > Memory used for buffers and cache - name: swap.total diff --git a/x-pack/metricbeat/module/panos/certificates/certificates.go b/x-pack/metricbeat/module/panos/system/certificates.go similarity index 54% rename from x-pack/metricbeat/module/panos/certificates/certificates.go rename to x-pack/metricbeat/module/panos/system/certificates.go index 508e6d68df6..36b5572e0ea 100644 --- a/x-pack/metricbeat/module/panos/certificates/certificates.go +++ b/x-pack/metricbeat/module/panos/system/certificates.go @@ -2,7 +2,7 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package certificates +package system import ( "encoding/xml" @@ -10,98 +10,32 @@ import ( "strings" "time" - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - "github.com/elastic/elastic-agent-libs/logp" "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" -) - -const ( - metricsetName = "certificates" - vsys = "" - query = "" ) -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - config panos.Config - logger *logp.Logger - client *pango.Firewall -} - -// New creates a new instance of the MetricSet. New is responsible for unpacking -// any MetricSet specific configuration options if there are any. -func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos certificates metricset is beta.") - - config := panos.Config{} - logger := logp.NewLogger(base.FullyQualifiedName()) - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - - return &MetricSet{ - BaseMetricSet: base, - config: config, - logger: logger, - client: client, - }, nil -} - -// Fetch method implements the data gathering and data conversion to the right -// format. It publishes the event which is then forwarded to the output. In case -// of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - log.Debugf("panos certificates.Fetch initialized client") +func getCertificateEvents(m *MetricSet) ([]mb.Event, error) { + query := "" + var response CertificateResponse output, err := m.client.Op(query, vsys, nil, nil) if err != nil { - log.Error("Error: %s", err) - return err + m.logger.Error("Error: %s", err) + return nil, err } err = xml.Unmarshal(output, &response) if err != nil { - log.Error("Error: %s", err) - return err + m.logger.Error("Error: %s", err) + return nil, err } - events := getEvents(m, response.Result) - - for _, event := range events { - report.Event(event) - } + events := formatCertificateEvents(m, response.Result) - return nil + return events, nil } -func getEvents(m *MetricSet, input string) []mb.Event { +func formatCertificateEvents(m *MetricSet, input string) []mb.Event { currentTime := time.Now() certificates := parseCertificates(input) @@ -121,12 +55,15 @@ func getEvents(m *MetricSet, input string) []mb.Event { "db_file": certificate.DBFile, "db_name": certificate.DBName, "db_status": certificate.DBStatus, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, }} - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - } + events = append(events, event) } diff --git a/x-pack/metricbeat/module/panos/system/fans.go b/x-pack/metricbeat/module/panos/system/fans.go new file mode 100644 index 00000000000..3b1dca2e93b --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/fans.go @@ -0,0 +1,64 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getFanEvents(m *MetricSet) ([]mb.Event, error) { + query := "" + var response FanResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatFanEvents(m, &response) + + return events, nil +} + +func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { + log := m.Logger() + events := make([]mb.Event, 0, len(response.Result.Fan.Slots)) + currentTime := time.Now() + var event mb.Event + for _, slot := range response.Result.Fan.Slots { + for _, entry := range slot.Entries { + log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) + event = mb.Event{MetricSetFields: mapstr.M{ + "slot_number": entry.Slot, + "description": entry.Description, + "alarm": entry.Alarm, + "rpm": entry.RPMs, + "min_rpm": entry.Min, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/system/filesystem.go b/x-pack/metricbeat/module/panos/system/filesystem.go new file mode 100644 index 00000000000..a9017242235 --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/filesystem.go @@ -0,0 +1,100 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "strings" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getFilesystemEvents(m *MetricSet) ([]mb.Event, error) { + query := "" + + var response FilesystemResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + filesystems := getFilesystems(response.Result.Data) + events := formatFilesytemEvents(m, filesystems) + + return events, nil +} + +/* +Result from the XML API call is basically linux df -h output: +Filesystem Size Used Avail Use% Mounted on +/dev/root 9.5G 4.0G 5.1G 44% / +none 2.5G 64K 2.5G 1% /dev +/dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg +/dev/sda6 7.6G 3.1G 4.2G 43% /opt/panrepo +tmpfs 2.5G 399M 2.1G 16% /dev/shm +cgroup_root 2.5G 0 2.5G 0% /cgroup +/dev/sda8 173G 63G 102G 39% /opt/panlogs +tmpfs 12M 44K 12M 1% /opt/pancfg/mgmt/ssl/private +*/ +func getFilesystems(input string) []Filesystem { + lines := strings.Split(input, "\n") + filesystems := make([]Filesystem, 0) + + // Skip the first line which is the header + for _, line := range lines[1:] { + fields := strings.Fields(line) + if len(fields) == 6 { + filesystem := Filesystem{ + Name: fields[0], + Size: fields[1], + Used: fields[2], + Avail: fields[3], + UsePerc: fields[4], + Mounted: fields[5], + } + filesystems = append(filesystems, filesystem) + } + } + return filesystems +} + +func formatFilesytemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { + events := make([]mb.Event, 0, len(filesystems)) + + currentTime := time.Now() + + for _, filesystem := range filesystems { + event := mb.Event{MetricSetFields: mapstr.M{ + "name": filesystem.Name, + "size": filesystem.Size, + "used": filesystem.Used, + "available": filesystem.Avail, + "use_percent": filesystem.UsePerc, + "mounted": filesystem.Mounted, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + + events = append(events, event) + } + + return events + +} diff --git a/x-pack/metricbeat/module/panos/system/license.go b/x-pack/metricbeat/module/panos/system/license.go new file mode 100644 index 00000000000..c6c5425b58a --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/license.go @@ -0,0 +1,65 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { + query := "" + var response LicenseResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatLicenseEvents(m, response.Result.Licenses) + + return events, nil + +} + +func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { + events := make([]mb.Event, 0, len(licenses)) + + currentTime := time.Now() + + for _, license := range licenses { + event := mb.Event{MetricSetFields: mapstr.M{ + "feature": license.Feature, + "description": license.Description, + "serial": license.Serial, + "issued": license.Issued, + "expires": license.Expires, + "expired": license.Expired, + "auth_code": license.AuthCode, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + + events = append(events, event) + } + + return events + +} diff --git a/x-pack/metricbeat/module/panos/system/power.go b/x-pack/metricbeat/module/panos/system/power.go new file mode 100644 index 00000000000..35b6f4ef047 --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/power.go @@ -0,0 +1,67 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getPowerEvents(m *MetricSet) ([]mb.Event, error) { + + query := "" + var response PowerResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatPowerEvents(m, &response) + + return events, nil +} + +func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { + log := m.Logger() + events := make([]mb.Event, 0, len(response.Result.Power.Slots)) + currentTime := time.Now() + var event mb.Event + for _, slot := range response.Result.Power.Slots { + for _, entry := range slot.Entries { + log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) + event = mb.Event{MetricSetFields: mapstr.M{ + + "slot_number": entry.Slot, + "description": entry.Description, + "alarm": entry.Alarm, + "volts": entry.Volts, + "minimum_volts": entry.MinimumVolts, + "maximum_volts": entry.MaximumVolts, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/system/resources.go b/x-pack/metricbeat/module/panos/system/resources.go new file mode 100644 index 00000000000..c3d5955c7b7 --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/resources.go @@ -0,0 +1,231 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "fmt" + "regexp" + "strings" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getResourceEvents(m *MetricSet) ([]mb.Event, error) { + var response ResourceResponse + query := "" + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatResourceEvents(m, response.Result) + + return events, nil +} + +/* +Output from the XML API call is the standard "top" output: + +top - 07:51:37 up 108 days, 1:38, 0 users, load average: 5.52, 5.79, 5.99 +Tasks: 189 total, 7 running, 182 sleeping, 0 stopped, 0 zombie +%Cpu(s): 73.0 us, 4.6 sy, 0.0 ni, 21.7 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st +MiB Mem : 5026.9 total, 414.2 free, 2541.5 used, 2071.1 buff/cache +MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem + + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 5692 20 0 121504 8396 6644 R 94.4 0.2 155491:08 pan_task + 5695 20 0 121504 7840 6632 R 94.4 0.2 155491:01 pan_task + 5696 20 0 121504 8360 6816 R 94.4 0.2 155486:29 pan_task + 5699 20 0 121504 8132 6676 R 94.4 0.2 155236:17 pan_task + 5700 20 0 146304 18424 6780 R 88.9 0.4 155491:40 pan_task + +22360 nobody 20 0 459836 40592 10148 R 22.2 0.8 0:38.65 httpd + + 6374 17 -3 1078156 18272 9716 S 5.6 0.4 215:46.41 routed + +14227 20 0 18108 7184 2172 R 5.6 0.1 0:00.04 top + + 1 20 0 2532 696 656 S 0.0 0.0 3:48.14 init + 2 20 0 0 0 0 S 0.0 0.0 0:00.83 kthreadd +*/ +func formatResourceEvents(m *MetricSet, input string) []mb.Event { + currentTime := time.Now() + events := make([]mb.Event, 0, 1) + + // We only need the top 5 lines + lines := strings.Split(input, "\n") + lines = lines[:5] + + systemInfo := parseSystemInfo(lines[0]) + taskInfo := parseTaskInfo(lines[1]) + cpuInfo := parseCPUInfo(lines[2]) + memoryInfo := parseMemoryInfo(lines[3]) + swapInfo := parseSwapInfo(lines[4]) + + event := mb.Event{MetricSetFields: mapstr.M{ + "uptime.days": systemInfo.Uptime.Days, + "uptime.hours": systemInfo.Uptime.Hours, + "user_count": systemInfo.UserCount, + "load_average.1m": systemInfo.LoadAverage.one_minute, + "load_average.5m": systemInfo.LoadAverage.five_minute, + "load_average.15m": systemInfo.LoadAverage.fifteen_minute, + "tasks.total": taskInfo.Total, + "tasks.running": taskInfo.Running, + "tasks.sleeping": taskInfo.Sleeping, + "tasks.stopped": taskInfo.Stopped, + "tasks.zombie": taskInfo.Zombie, + "cpu.user": cpuInfo.User, + "cpu.system": cpuInfo.System, + "cpu.nice": cpuInfo.Nice, + "cpu.idle": cpuInfo.Idle, + "cpu.wait": cpuInfo.Wait, + "cpu.hi": cpuInfo.Hi, + "cpu.system_int": cpuInfo.SystemInt, + "cpu.steal": cpuInfo.Steal, + "memory.total": memoryInfo.Total, + "memory.free": memoryInfo.Free, + "memory.used": memoryInfo.Used, + "memory.buffer_cache": memoryInfo.BufferCache, + "swap.total": swapInfo.Total, + "swap.free": swapInfo.Free, + "swap.used": swapInfo.Used, + "swap.available": swapInfo.Available, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + + events = append(events, event) + return events +} + +func parseSystemInfo(line string) SystemInfo { + // top - 07:51:37 up 108 days, 1:38, 0 users, load average: 5.52, 5.79, 5.99 + re := regexp.MustCompile(`\s+`) + normal := re.ReplaceAllString(line, " ") + fields := strings.Split(normal, " ") + + uptime := Uptime{parseInt(fields[4]), fields[6]} + loadAverage := strings.Split(normal, ": ")[1] + loadAverageValues := strings.Split(loadAverage, ", ") + + users := fields[7] + var loadAverageFloat []float64 + for _, value := range loadAverageValues { + loadAverageFloat = append(loadAverageFloat, parseFloat(value)) + } + + SystemLoad := SystemLoad{loadAverageFloat[0], loadAverageFloat[1], loadAverageFloat[2]} + return SystemInfo{ + Uptime: uptime, + UserCount: parseInt(users), + LoadAverage: SystemLoad, + } +} + +func parseTaskInfo(line string) TaskInfo { + //Tasks: 189 total, 7 running, 182 sleeping, 0 stopped, 0 zombie + values := strings.Fields(line) + + total := parseInt(values[1]) + running := parseInt(values[3]) + sleeping := parseInt(values[5]) + stopped := parseInt(values[7]) + zombie := parseInt(values[9]) + + return TaskInfo{ + Total: total, + Running: running, + Sleeping: sleeping, + Stopped: stopped, + Zombie: zombie, + } +} + +func parseCPUInfo(line string) CPUInfo { + //%Cpu(s): 73.0 us, 4.6 sy, 0.0 ni, 21.7 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st + values := strings.Fields(line) + + user := parseFloat(values[1]) + system := parseFloat(values[3]) + nice := parseFloat(values[5]) + idle := parseFloat(values[7]) + wait := parseFloat(values[9]) + hi := parseFloat(values[11]) + systemInt := parseFloat(values[13]) + steal := parseFloat(values[15]) + + return CPUInfo{ + User: user, + System: system, + Nice: nice, + Idle: idle, + Wait: wait, + Hi: hi, + SystemInt: systemInt, + Steal: steal, + } +} + +func parseMemoryInfo(line string) MemoryInfo { + //MiB Mem : 5026.9 total, 414.2 free, 2541.5 used, 2071.1 buff/cache + values := strings.Fields(line) + + total := parseFloat(values[3]) + free := parseFloat(values[5]) + used := parseFloat(values[7]) + bufferCache := parseFloat(values[9]) + + return MemoryInfo{ + Total: total, + Free: free, + Used: used, + BufferCache: bufferCache, + } +} + +func parseSwapInfo(line string) SwapInfo { + //MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem + values := strings.Fields(line) + + total := parseFloat(values[2]) + free := parseFloat(values[4]) + used := parseFloat(values[6]) + available := parseFloat(values[8]) + + return SwapInfo{ + Total: total, + Free: free, + Used: used, + Available: available, + } +} + +func parseFloat(value string) float64 { + var result float64 + fmt.Sscanf(value, "%f", &result) + return result +} + +func parseInt(value string) int { + var result int + fmt.Sscanf(value, "%d", &result) + return result +} diff --git a/x-pack/metricbeat/module/panos/system/system.go b/x-pack/metricbeat/module/panos/system/system.go index 73490699f0b..a4d38ed0ed3 100644 --- a/x-pack/metricbeat/module/panos/system/system.go +++ b/x-pack/metricbeat/module/panos/system/system.go @@ -5,24 +5,18 @@ package system import ( - "encoding/xml" - "fmt" - "regexp" + "errors" "strings" - "time" - "github.com/PaloAltoNetworks/pango" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" ) const ( metricsetName = "system" vsys = "" - query = "" ) // MetricSet holds any configuration or state information. It must implement @@ -31,9 +25,9 @@ const ( // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - config panos.Config + config *panos.Config logger *logp.Logger - client *pango.Firewall + client panos.PanosClient } // init registers the MetricSet with the central registry as soon as the program @@ -47,17 +41,20 @@ func init() { // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos licenses metricset is beta.") + cfgwarn.Beta("The panos system metricset is beta.") + + config, err := panos.NewConfig(base) + if err != nil { + return nil, err + } - config := panos.Config{} logger := logp.NewLogger(base.FullyQualifiedName()) - if err := base.Module().UnpackConfig(&config); err != nil { + //client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + client, err := panos.GetPanosClient(config) + if err != nil { return nil, err } - logger.Debugf("panos_licenses metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} return &MetricSet{ BaseMetricSet: base, @@ -71,197 +68,85 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response + // accumulate errs and report them all at the end so that we don't + // stop processing events if one of the fetches fails + var errs []string - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err + certificateEvents, err := getCertificateEvents(m) + if err != nil { + m.logger.Error("Error get certificate events: %s", err) + errs = append(errs, err.Error()) } - log.Infof("panos_licenses.Fetch initialized client") - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err + for _, event := range certificateEvents { + report.Event(event) } - err = xml.Unmarshal(output, &response) + resourceEvents, err := getResourceEvents(m) if err != nil { - log.Error("Error: %s", err) - return err + m.logger.Error("Error get resource events: %s", err) + errs = append(errs, err.Error()) } - event := getEvent(m, response.Result) - report.Event(*event) - - return nil -} - -func getEvent(m *MetricSet, input string) *mb.Event { - currentTime := time.Now() - - // The output is standard "top" output, and we only need the top 5 lines - lines := strings.Split(input, "\n") - lines = lines[:5] - - systemInfo := parseSystemInfo(lines[0]) - taskInfo := parseTaskInfo(lines[1]) - cpuInfo := parseCPUInfo(lines[2]) - memoryInfo := parseMemoryInfo(lines[3]) - swapInfo := parseSwapInfo(lines[4]) - - event := mb.Event{MetricSetFields: mapstr.M{ - "uptime.days": systemInfo.Uptime.Days, - "uptime.hours": systemInfo.Uptime.Hours, - "user_count": systemInfo.UserCount, - "load_average.1m": systemInfo.LoadAverage.one_minute, - "load_average.5m": systemInfo.LoadAverage.five_minute, - "load_average.15m": systemInfo.LoadAverage.fifteen_minute, - "tasks.total": taskInfo.Total, - "tasks.running": taskInfo.Running, - "tasks.sleeping": taskInfo.Sleeping, - "tasks.stopped": taskInfo.Stopped, - "tasks.zombie": taskInfo.Zombie, - "cpu.user": cpuInfo.User, - "cpu.system": cpuInfo.System, - "cpu.nice": cpuInfo.Nice, - "cpu.idle": cpuInfo.Idle, - "cpu.wait": cpuInfo.Wait, - "cpu.hi": cpuInfo.Hi, - "cpu.system_int": cpuInfo.SystemInt, - "cpu.steal": cpuInfo.Steal, - "memory.total": memoryInfo.Total, - "memory.free": memoryInfo.Free, - "memory.used": memoryInfo.Used, - "memory.buffer_cache": memoryInfo.BufferCache, - "swap.total": swapInfo.Total, - "swap.free": swapInfo.Free, - "swap.used": swapInfo.Used, - "swap.available": swapInfo.Available, - }} - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", + for _, event := range resourceEvents { + report.Event(event) } - return &event -} - -func parseSystemInfo(line string) SystemInfo { - // top - 07:51:37 up 108 days, 1:38, 0 users, load average: 5.52, 5.79, 5.99 - re := regexp.MustCompile(`\s+`) - normal := re.ReplaceAllString(line, " ") - fields := strings.Split(normal, " ") - - uptime := Uptime{parseInt(fields[4]), fields[6]} - loadAverage := strings.Split(normal, ": ")[1] - loadAverageValues := strings.Split(loadAverage, ", ") + powerEvents, err := getPowerEvents(m) + if err != nil { + m.logger.Error("Error get power events: %s", err) + errs = append(errs, err.Error()) - users := fields[7] - var loadAverageFloat []float64 - for _, value := range loadAverageValues { - loadAverageFloat = append(loadAverageFloat, parseFloat(value)) } - SystemLoad := SystemLoad{loadAverageFloat[0], loadAverageFloat[1], loadAverageFloat[2]} - return SystemInfo{ - Uptime: uptime, - UserCount: parseInt(users), - LoadAverage: SystemLoad, + for _, event := range powerEvents { + report.Event(event) } -} -func parseTaskInfo(line string) TaskInfo { - //Tasks: 189 total, 7 running, 182 sleeping, 0 stopped, 0 zombie - values := strings.Fields(line) - - total := parseInt(values[1]) - running := parseInt(values[3]) - sleeping := parseInt(values[5]) - stopped := parseInt(values[7]) - zombie := parseInt(values[9]) - - return TaskInfo{ - Total: total, - Running: running, - Sleeping: sleeping, - Stopped: stopped, - Zombie: zombie, + fanEvents, err := getFanEvents(m) + if err != nil { + m.logger.Error("Error get fan events: %s", err) + errs = append(errs, err.Error()) } -} - -func parseCPUInfo(line string) CPUInfo { - //%Cpu(s): 73.0 us, 4.6 sy, 0.0 ni, 21.7 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st - values := strings.Fields(line) - user := parseFloat(values[1]) - system := parseFloat(values[3]) - nice := parseFloat(values[5]) - idle := parseFloat(values[7]) - wait := parseFloat(values[9]) - hi := parseFloat(values[11]) - systemInt := parseFloat(values[13]) - steal := parseFloat(values[15]) - - return CPUInfo{ - User: user, - System: system, - Nice: nice, - Idle: idle, - Wait: wait, - Hi: hi, - SystemInt: systemInt, - Steal: steal, + for _, event := range fanEvents { + report.Event(event) } -} -func parseMemoryInfo(line string) MemoryInfo { - //MiB Mem : 5026.9 total, 414.2 free, 2541.5 used, 2071.1 buff/cache - values := strings.Fields(line) + thermalEvents, err := getThermalEvents(m) + if err != nil { + m.logger.Error("Error get thermal events: %s", err) + errs = append(errs, err.Error()) + } - total := parseFloat(values[3]) - free := parseFloat(values[5]) - used := parseFloat(values[7]) - bufferCache := parseFloat(values[9]) + for _, event := range thermalEvents { + report.Event(event) + } - return MemoryInfo{ - Total: total, - Free: free, - Used: used, - BufferCache: bufferCache, + licenesEvents, err := getLicenseEvents(m) + if err != nil { + m.logger.Error("Error get license events: %s", err) + errs = append(errs, err.Error()) } -} -func parseSwapInfo(line string) SwapInfo { - //MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem - values := strings.Fields(line) + for _, event := range licenesEvents { + report.Event(event) + } - total := parseFloat(values[2]) - free := parseFloat(values[4]) - used := parseFloat(values[6]) - available := parseFloat(values[8]) + filesystemEvents, err := getFilesystemEvents(m) + if err != nil { + m.logger.Error("Error get filesystem events: %s", err) + errs = append(errs, err.Error()) + } - return SwapInfo{ - Total: total, - Free: free, - Used: used, - Available: available, + for _, event := range filesystemEvents { + report.Event(event) } -} -func parseFloat(value string) float64 { - var result float64 - fmt.Sscanf(value, "%f", &result) - return result -} + if len(errs) > 0 { + return errors.New(strings.Join(errs, "; ")) + } else { + return nil + } -func parseInt(value string) int { - var result int - fmt.Sscanf(value, "%d", &result) - return result } diff --git a/x-pack/metricbeat/module/panos/system/system_types.go b/x-pack/metricbeat/module/panos/system/system_types.go new file mode 100644 index 00000000000..9c3a6468f20 --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/system_types.go @@ -0,0 +1,209 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import "encoding/xml" + +// system resources +type ResourceResponse struct { + Status string `xml:"status,attr"` + Result string `xml:"result"` +} + +type SystemLoad struct { + one_minute float64 + five_minute float64 + fifteen_minute float64 +} + +type Uptime struct { + Days int + Hours string +} + +type SystemInfo struct { + Uptime Uptime + UserCount int + LoadAverage SystemLoad +} + +type TaskInfo struct { + Total int + Running int + Sleeping int + Stopped int + Zombie int +} + +type CPUInfo struct { + User float64 + System float64 + Nice float64 + Idle float64 + Wait float64 + Hi float64 + SystemInt float64 + Steal float64 +} + +type MemoryInfo struct { + Total float64 + Free float64 + Used float64 + BufferCache float64 +} + +type SwapInfo struct { + Total float64 + Free float64 + Used float64 + Available float64 +} + +// temperature +type ThermalResponse struct { + Status string `xml:"status,attr"` + Result ThermalResult `xml:"result"` +} + +type ThermalResult struct { + Thermal Thermal `xml:"thermal"` +} + +type Thermal struct { + Slots []ThermalSlot `xml:",any"` +} + +type ThermalSlot struct { + Name xml.Name `xml:",any"` + Entries []ThermalEntry `xml:"entry"` +} + +type ThermalEntry struct { + Slot int `xml:"slot"` + Description string `xml:"description"` + Alarm bool `xml:"alarm"` + DegreesCelsius float64 `xml:"DegreesC"` + MinimumTemp float64 `xml:"min"` + MaximumTemp float64 `xml:"max"` +} + +// power + +type PowerResponse struct { + Status string `xml:"status,attr"` + Result PowerResult `xml:"result"` +} + +type PowerResult struct { + Power Power `xml:"power"` +} + +type Power struct { + Slots []PowerSlot `xml:",any"` +} + +type PowerSlot struct { + Entries []PowerEntry `xml:"entry"` +} + +type PowerEntry struct { + Slot int `xml:"slot"` + Description string `xml:"description"` + Alarm bool `xml:"alarm"` + Volts float64 `xml:"Volts"` + MinimumVolts float64 `xml:"min"` + MaximumVolts float64 `xml:"max"` +} + +// fans + +type FanResponse struct { + Status string `xml:"status,attr"` + Result FanResult `xml:"result"` +} + +type FanResult struct { + Fan Fan `xml:"fan"` +} + +type Fan struct { + Slots []FanSlot `xml:",any"` +} + +type FanSlot struct { + Entries []FanEntry `xml:"entry"` +} + +type FanEntry struct { + Slot int `xml:"slot"` + Description string `xml:"description"` + Alarm string `xml:"alarm"` + RPMs int `xml:"RPMs"` + Min int `xml:"min"` +} + +// filesystem + +type FilesystemResponse struct { + XMLName xml.Name `xml:"response"` + Status string `xml:"status,attr"` + Result FilesystemResult `xml:"result"` +} + +type FilesystemResult struct { + Data string `xml:",cdata"` +} + +type Filesystem struct { + Name string + Size string + Used string + Avail string + UsePerc string + Mounted string +} + +// licenses + +type LicenseResponse struct { + Status string `xml:"status,attr"` + Result LicenseResult `xml:"result"` +} + +type LicenseResult struct { + Licenses []License `xml:"licenses>entry"` +} + +type License struct { + Feature string `xml:"feature"` + Description string `xml:"description"` + Serial string `xml:"serial"` + Issued string `xml:"issued"` + Expires string `xml:"expires"` + Expired string `xml:"expired"` + AuthCode string `xml:"authcode"` +} + +// certificates + +type CertificateResponse struct { + Status string `xml:"status,attr"` + Result string `xml:"result"` +} + +type Certificate struct { + CertName string + Issuer string + IssuerSubjectHash string + IssuerKeyHash string + DBType string + DBExpDate string + DBRevDate string + DBSerialNo string + DBFile string + DBName string + DBStatus string +} diff --git a/x-pack/metricbeat/module/panos/system/thermal.go b/x-pack/metricbeat/module/panos/system/thermal.go new file mode 100644 index 00000000000..6a89eeb5130 --- /dev/null +++ b/x-pack/metricbeat/module/panos/system/thermal.go @@ -0,0 +1,68 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getThermalEvents(m *MetricSet) ([]mb.Event, error) { + var response ThermalResponse + + query := "" + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatThermalEvents(m, &response) + + return events, nil + +} + +func formatThermalEvents(m *MetricSet, response *ThermalResponse) []mb.Event { + log := m.Logger() + events := make([]mb.Event, 0, len(response.Result.Thermal.Slots)) + currentTime := time.Now() + var event mb.Event + for _, slot := range response.Result.Thermal.Slots { + for _, entry := range slot.Entries { + log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) + event = mb.Event{MetricSetFields: mapstr.M{ + + "slot_number": entry.Slot, + "description": entry.Description, + "alarm": entry.Alarm, + "degress_celsius": entry.DegreesCelsius, + "minimum_temp": entry.MinimumTemp, + "maximum_temp": entry.MaximumTemp, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/system/types.go b/x-pack/metricbeat/module/panos/system/types.go.old similarity index 100% rename from x-pack/metricbeat/module/panos/system/types.go rename to x-pack/metricbeat/module/panos/system/types.go.old diff --git a/x-pack/metricbeat/module/panos/temperature/_meta/data.json b/x-pack/metricbeat/module/panos/temperature/_meta/data.json deleted file mode 100644 index 7054ce03033..00000000000 --- a/x-pack/metricbeat/module/panos/temperature/_meta/data.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "@timestamp":"2016-05-23T08:05:34.853Z", - "beat":{ - "hostname":"beathost", - "name":"beathost" - }, - "metricset":{ - "host":"localhost", - "module":"panos", - "name":"temperature", - "rtt":44269 - }, - "panos":{ - "temperature":{ - "example": "temperature" - } - }, - "type":"metricsets" -} diff --git a/x-pack/metricbeat/module/panos/temperature/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/temperature/_meta/docs.asciidoc deleted file mode 100644 index 6f9d6b27f9e..00000000000 --- a/x-pack/metricbeat/module/panos/temperature/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the temperature metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml b/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml deleted file mode 100644 index 324bf8288a7..00000000000 --- a/x-pack/metricbeat/module/panos/temperature/_meta/fields.yml +++ /dev/null @@ -1,23 +0,0 @@ -- name: temperature - type: group - release: beta - description: temperature - fields: - - name: slot_number - type: integer - description: Slot number field - - name: description - type: text - description: Description field - - name: alarm - type: boolean - description: Alarm field - - name: degrees_celsius - type: float - description: Degrees Celsius field - - name: minimum_temp - type: float - description: Minimum temperature field - - name: maximum_temp - type: float - description: Maximum temperature field diff --git a/x-pack/metricbeat/module/panos/temperature/temperature.go b/x-pack/metricbeat/module/panos/temperature/temperature.go deleted file mode 100644 index 4948b93a6df..00000000000 --- a/x-pack/metricbeat/module/panos/temperature/temperature.go +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package temperature - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" -) - -const ( - metricsetName = "temperature" - vsys = "" - query = "" -) - -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - config panos.Config - logger *logp.Logger - client *pango.Firewall -} - -// New creates a new instance of the MetricSet. New is responsible for unpacking -// any MetricSet specific configuration options if there are any. -func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos temperature metricset is beta.") - - config := panos.Config{} - logger := logp.NewLogger(base.FullyQualifiedName()) - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - logger.Debugf("panos_temperature metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - - return &MetricSet{ - BaseMetricSet: base, - config: config, - logger: logger, - client: client, - }, nil -} - -// Fetch method implements the data gathering and data conversion to the right -// format. It publishes the event which is then forwarded to the output. In case -// of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - log.Debug("panos_temperature. Fetch initialized client") - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - log.Error("Error: %s", err) - return err - } - - events := getEvents(m, &response) - - for _, event := range events { - report.Event(event) - } - - return nil -} - -func getEvents(m *MetricSet, response *Response) []mb.Event { - log := m.Logger() - events := make([]mb.Event, 0, len(response.Result.Thermal.Slots)) - currentTime := time.Now() - var event mb.Event - for _, slot := range response.Result.Thermal.Slots { - for _, entry := range slot.Entries { - log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) - event = mb.Event{MetricSetFields: mapstr.M{ - - "slot_number": entry.Slot, - "description": entry.Description, - "alarm": entry.Alarm, - "degress_celsius": entry.DegreesCelsius, - "minimum_temp": entry.MinimumTemp, - "maximum_temp": entry.MaximumTemp, - }} - } - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - events = append(events, event) - } - - return events -} diff --git a/x-pack/metricbeat/module/panos/temperature/types.go b/x-pack/metricbeat/module/panos/temperature/types.go deleted file mode 100644 index 6de010560d4..00000000000 --- a/x-pack/metricbeat/module/panos/temperature/types.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package temperature - -import "encoding/xml" - -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Thermal Thermal `xml:"thermal"` -} - -type Thermal struct { - Slots []Slot `xml:",any"` -} - -type Slot struct { - Name xml.Name `xml:",any"` - Entries []Entry `xml:"entry"` -} - -type Entry struct { - Slot int `xml:"slot"` - Description string `xml:"description"` - Alarm bool `xml:"alarm"` - DegreesCelsius float64 `xml:"DegreesC"` - MinimumTemp float64 `xml:"min"` - MaximumTemp float64 `xml:"max"` -} diff --git a/x-pack/metricbeat/module/panos/tunnels/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/tunnels/_meta/docs.asciidoc deleted file mode 100644 index fd0b68b3aa0..00000000000 --- a/x-pack/metricbeat/module/panos/tunnels/_meta/docs.asciidoc +++ /dev/null @@ -1 +0,0 @@ -This is the tunnels metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml b/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml deleted file mode 100644 index 4296184ef8f..00000000000 --- a/x-pack/metricbeat/module/panos/tunnels/_meta/fields.yml +++ /dev/null @@ -1,59 +0,0 @@ -- name: tunnels - type: group - release: beta - description: ipsec tunnels - fields: - - name: id - type: integer - description: ID field - - name: name - type: keyword - description: Name field - - name: gw - type: keyword - description: Gateway field - - name: TSi_ip - type: ip - description: TSi IP field - - name: TSi_prefix - type: integer - description: TSi Prefix field - - name: TSi_proto - type: integer - description: TSi Protocol field - - name: TSi_port - type: integer - description: TSi Port field - - name: TSr_ip - type: ip - description: TSr IP field - - name: TSr_prefix - type: integer - description: TSr Prefix field - - name: TSr_proto - type: integer - description: TSr Protocol field - - name: TSr_port - type: integer - description: TSr Port field - - name: proto - type: integer - description: Protocol field - - name: mode - type: keyword - description: Mode field - - name: dh - type: keyword - description: DH field - - name: enc - type: keyword - description: Encryption field - - name: hash - type: keyword - description: Hash field - - name: life - type: integer - description: Life field - - name: kb - type: integer - description: KB field diff --git a/x-pack/metricbeat/module/panos/tunnels/tunnels.go b/x-pack/metricbeat/module/panos/tunnels/tunnels.go deleted file mode 100644 index 8206a8fdea3..00000000000 --- a/x-pack/metricbeat/module/panos/tunnels/tunnels.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package tunnels - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" -) - -const ( - metricsetName = "tunnels" - vsys = "" - query = "" -) - -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - -// MetricSet holds any configuration or state information. It must implement -// the mb.MetricSet interface. And this is best achieved by embedding -// mb.BaseMetricSet because it implements all of the required mb.MetricSet -// interface methods except for Fetch. -type MetricSet struct { - mb.BaseMetricSet - config panos.Config - logger *logp.Logger - client *pango.Firewall -} - -// New creates a new instance of the MetricSet. New is responsible for unpacking -// any MetricSet specific configuration options if there are any. -func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos tunnels metricset is beta.") - - config := panos.Config{} - logger := logp.NewLogger(base.FullyQualifiedName()) - - if err := base.Module().UnpackConfig(&config); err != nil { - return nil, err - } - logger.Debugf("panos_licenses metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - - return &MetricSet{ - BaseMetricSet: base, - config: config, - logger: logger, - client: client, - }, nil -} - -// Fetch method implements the data gathering and data conversion to the right -// format. It publishes the event which is then forwarded to the output. In case -// of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response - - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err - } - log.Infof("panos_tunnels.Fetch initialized client") - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - log.Error("Error: %s", err) - return err - } - - events := getEvents(m, response.Result.Entries) - - for _, event := range events { - report.Event(event) - } - - return nil -} - -func getEvents(m *MetricSet, entries []Entry) []mb.Event { - events := make([]mb.Event, 0, len(entries)) - - currentTime := time.Now() - - for _, entry := range entries { - event := mb.Event{MetricSetFields: mapstr.M{ - "id": entry.ID, - "name": entry.Name, - "gw": entry.GW, - "TSi_ip": entry.TSiIP, - "TSi_prefix": entry.TSiPrefix, - "TSi_proto": entry.TSiProto, - "TSi_port": entry.TSiPort, - "TSr_ip": entry.TSrIP, - "TSr_prefix": entry.TSrPrefix, - "TSr_proto": entry.TSrProto, - "TSr_port": entry.TSrPort, - "proto": entry.Proto, - "mode": entry.Mode, - "dh": entry.DH, - "enc": entry.Enc, - "hash": entry.Hash, - "life": entry.Life, - "kb": entry.KB, - }} - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - - events = append(events, event) - } - - return events - -} diff --git a/x-pack/metricbeat/module/panos/tunnels/types.go b/x-pack/metricbeat/module/panos/tunnels/types.go deleted file mode 100644 index e839a26bfa2..00000000000 --- a/x-pack/metricbeat/module/panos/tunnels/types.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package tunnels - -type Response struct { - Status string `xml:"status,attr"` - Result Result `xml:"result"` -} - -type Result struct { - Entries []Entry `xml:"entries>entry"` - NTun int `xml:"ntun"` -} - -type Entry struct { - ID int `xml:"id"` - Name string `xml:"name"` - GW string `xml:"gw"` - TSiIP string `xml:"TSi_ip"` - TSiPrefix int `xml:"TSi_prefix"` - TSiProto int `xml:"TSi_proto"` - TSiPort int `xml:"TSi_port"` - TSrIP string `xml:"TSr_ip"` - TSrPrefix int `xml:"TSr_prefix"` - TSrProto int `xml:"TSr_proto"` - TSrPort int `xml:"TSr_port"` - Proto string `xml:"proto"` - Mode string `xml:"mode"` - DH string `xml:"dh"` - Enc string `xml:"enc"` - Hash string `xml:"hash"` - Life int `xml:"life"` - KB int `xml:"kb"` -} diff --git a/x-pack/metricbeat/module/panos/types.go b/x-pack/metricbeat/module/panos/types.go deleted file mode 100644 index d451f834dd3..00000000000 --- a/x-pack/metricbeat/module/panos/types.go +++ /dev/null @@ -1,11 +0,0 @@ -package panos - -const ( - ModuleName = "panos" -) - -type Config struct { - HostIp string `config:"host_ip"` - ApiKey string `config:"apiKey"` - DebugMode string `config:"apiDebugMode"` -} diff --git a/x-pack/metricbeat/module/panos/fans/_meta/data.json b/x-pack/metricbeat/module/panos/vpn/_meta/data.json similarity index 80% rename from x-pack/metricbeat/module/panos/fans/_meta/data.json rename to x-pack/metricbeat/module/panos/vpn/_meta/data.json index 34a471bde92..29d8ad34b1c 100644 --- a/x-pack/metricbeat/module/panos/fans/_meta/data.json +++ b/x-pack/metricbeat/module/panos/vpn/_meta/data.json @@ -7,12 +7,12 @@ "metricset":{ "host":"localhost", "module":"panos", - "name":"fans", + "name":"vpn", "rtt":44269 }, "panos":{ - "fans":{ - "example": "fans" + "vpn":{ + "example": "vpn" } }, "type":"metricsets" diff --git a/x-pack/metricbeat/module/panos/vpn/_meta/docs.asciidoc b/x-pack/metricbeat/module/panos/vpn/_meta/docs.asciidoc new file mode 100644 index 00000000000..9bed75b14c2 --- /dev/null +++ b/x-pack/metricbeat/module/panos/vpn/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the vpn metricset of the module panos. diff --git a/x-pack/metricbeat/module/panos/vpn/_meta/fields.yml b/x-pack/metricbeat/module/panos/vpn/_meta/fields.yml new file mode 100644 index 00000000000..bea23e35c83 --- /dev/null +++ b/x-pack/metricbeat/module/panos/vpn/_meta/fields.yml @@ -0,0 +1,10 @@ +- name: vpn + type: group + release: beta + description: > + vpn + fields: + - name: example + type: keyword + description: > + Example field diff --git a/x-pack/metricbeat/module/panos/vpn/gp_sessions.go b/x-pack/metricbeat/module/panos/vpn/gp_sessions.go new file mode 100644 index 00000000000..7566f8f36a3 --- /dev/null +++ b/x-pack/metricbeat/module/panos/vpn/gp_sessions.go @@ -0,0 +1,81 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package vpn + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getGlobalProtectSessionEvents(m *MetricSet) ([]mb.Event, error) { + query := "" + var response GPSessionsResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatGPSessionEvents(m, response.Result.Sessions) + + return events, nil + +} + +func formatGPSessionEvents(m *MetricSet, sessions []GPSession) []mb.Event { + events := make([]mb.Event, 0, len(sessions)) + + currentTime := time.Now() + + for _, session := range sessions { + event := mb.Event{MetricSetFields: mapstr.M{ + "domain": session.Domain, + "is_local": session.IsLocal, + "username": session.Username, + "primary_username": session.PrimaryUsername, + "region_for_config": session.RegionForConfig, + "source_region": session.SourceRegion, + "computer": session.Computer, + "client": session.Client, + "vpn_type": session.VPNType, + "host_id": session.HostID, + "app_version": session.AppVersion, + "virtual_ip": session.VirtualIP, + "virtual_ipv6": session.VirtualIPv6, + "public_ip": session.PublicIP, + "public_ipv6": session.PublicIPv6, + "tunnel_type": session.TunnelType, + "public_connection_ipv6": session.PublicConnectionIPv6, + "client_ip": session.ClientIP, + "login_time": session.LoginTime, + "login_time_utc": session.LoginTimeUTC, + "lifetime": session.Lifetime, + "request_login": session.RequestLogin, + "request_get_config": session.RequestGetConfig, + "request_sslvpn_connect": session.RequestSSLVPNConnect, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/vpn/gp_stats.go b/x-pack/metricbeat/module/panos/vpn/gp_stats.go new file mode 100644 index 00000000000..f211a6d3178 --- /dev/null +++ b/x-pack/metricbeat/module/panos/vpn/gp_stats.go @@ -0,0 +1,64 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package vpn + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getGlobalProtectStatsEvents(m *MetricSet) ([]mb.Event, error) { + query := "" + var response GPStatsResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatGPStatsEvents(m, response) + + return events, nil + +} + +func formatGPStatsEvents(m *MetricSet, response GPStatsResponse) []mb.Event { + events := make([]mb.Event, 0, len(response.Result.Gateways)) + + currentTime := time.Now() + totalCurrent := response.Result.TotalCurrentUsers + totalPrevious := response.Result.TotalPreviousUsers + + for _, gateway := range response.Result.Gateways { + event := mb.Event{MetricSetFields: mapstr.M{ + "gateway.name": gateway.Name, + "gateway.current_users": gateway.CurrentUsers, + "gateway.previous_users": gateway.PreviousUsers, + "total_current_users": totalCurrent, + "total_previous_users": totalPrevious, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/vpn/tunnels.go b/x-pack/metricbeat/module/panos/vpn/tunnels.go new file mode 100644 index 00000000000..9ef6904d4a7 --- /dev/null +++ b/x-pack/metricbeat/module/panos/vpn/tunnels.go @@ -0,0 +1,76 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package vpn + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func getIPSecTunnelEvents(m *MetricSet) ([]mb.Event, error) { + query := "" + var response TunnelsResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := getEvents(m, response.Result.Entries) + + return events, nil + +} + +func getEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { + events := make([]mb.Event, 0, len(entries)) + + currentTime := time.Now() + + for _, entry := range entries { + event := mb.Event{MetricSetFields: mapstr.M{ + "id": entry.ID, + "name": entry.Name, + "gw": entry.GW, + "TSi_ip": entry.TSiIP, + "TSi_prefix": entry.TSiPrefix, + "TSi_proto": entry.TSiProto, + "TSi_port": entry.TSiPort, + "TSr_ip": entry.TSrIP, + "TSr_prefix": entry.TSrPrefix, + "TSr_proto": entry.TSrProto, + "TSr_port": entry.TSrPort, + "proto": entry.Proto, + "mode": entry.Mode, + "dh": entry.DH, + "enc": entry.Enc, + "hash": entry.Hash, + "life": entry.Life, + "kb": entry.KB, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + "@Timestamp": currentTime, + }} + + events = append(events, event) + } + + return events + +} diff --git a/x-pack/metricbeat/module/panos/licenses/licenses.go b/x-pack/metricbeat/module/panos/vpn/vpn.go similarity index 52% rename from x-pack/metricbeat/module/panos/licenses/licenses.go rename to x-pack/metricbeat/module/panos/vpn/vpn.go index 50023cf7a01..903f579cfd9 100644 --- a/x-pack/metricbeat/module/panos/licenses/licenses.go +++ b/x-pack/metricbeat/module/panos/vpn/vpn.go @@ -2,60 +2,59 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package licenses +package vpn import ( - "encoding/xml" - "time" + "errors" + "strings" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" "github.com/elastic/elastic-agent-libs/logp" - "github.com/elastic/elastic-agent-libs/mapstr" - - "github.com/PaloAltoNetworks/pango" ) const ( - metricsetName = "licenses" + metricsetName = "vpn" vsys = "" - query = "" ) -// init registers the MetricSet with the central registry as soon as the program -// starts. The New function will be called later to instantiate an instance of -// the MetricSet for each host is defined in the module's configuration. After the -// MetricSet has been created then Fetch will begin to be called periodically. -func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) -} - // MetricSet holds any configuration or state information. It must implement // the mb.MetricSet interface. And this is best achieved by embedding // mb.BaseMetricSet because it implements all of the required mb.MetricSet // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - config panos.Config + config *panos.Config logger *logp.Logger - client *pango.Firewall + client panos.PanosClient +} + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each host is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) } // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos licenses metricset is beta.") + cfgwarn.Beta("The panos vpn metricset is beta.") + + config, err := panos.NewConfig(base) + if err != nil { + return nil, err + } - config := panos.Config{} logger := logp.NewLogger(base.FullyQualifiedName()) - if err := base.Module().UnpackConfig(&config); err != nil { + //client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + client, err := panos.GetPanosClient(config) + if err != nil { return nil, err } - logger.Debugf("panos_licenses metricset config: %v", config) - - client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} return &MetricSet{ BaseMetricSet: base, @@ -69,63 +68,44 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). func (m *MetricSet) Fetch(report mb.ReporterV2) error { - log := m.Logger() - var response Response + // accumulate errs and report them all at the end so that we don't + // stop processing events if one of the fetches fails + var errs []string - // Initialize the client - if err := m.client.Initialize(); err != nil { - log.Error("Failed to initialize client: %s", err) - return err + gpSessionEvents, err := getGlobalProtectSessionEvents(m) + if err != nil { + m.logger.Error("Error get GlobalProtect session events: %s", err) + errs = append(errs, err.Error()) } - log.Infof("panos_licenses.Fetch initialized client") - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - log.Error("Error: %s", err) - return err + for _, event := range gpSessionEvents { + report.Event(event) } - err = xml.Unmarshal(output, &response) + gpStatsEvents, err := getGlobalProtectStatsEvents(m) if err != nil { - log.Error("Error: %s", err) - return err + m.logger.Error("Error get GlobalProtect stats events: %s", err) + errs = append(errs, err.Error()) } - events := getEvents(m, response.Result.Licenses) - - for _, event := range events { + for _, event := range gpStatsEvents { report.Event(event) } - return nil -} + ipsecTunnelsEvents, err := getIPSecTunnelEvents(m) + if err != nil { + m.logger.Error("Error get GlobalProtect stats events: %s", err) + errs = append(errs, err.Error()) + } -func getEvents(m *MetricSet, licenses []License) []mb.Event { - events := make([]mb.Event, 0, len(licenses)) - - currentTime := time.Now() - - for _, license := range licenses { - event := mb.Event{MetricSetFields: mapstr.M{ - "feature": license.Feature, - "description": license.Description, - "serial": license.Serial, - "issued": license.Issued, - "expires": license.Expires, - "expired": license.Expired, - "auth_code": license.AuthCode, - }} - event.Timestamp = currentTime - event.RootFields = mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - } - - events = append(events, event) + for _, event := range ipsecTunnelsEvents { + report.Event(event) } - return events + if len(errs) > 0 { + return errors.New(strings.Join(errs, "; ")) + } else { + return nil + } } diff --git a/x-pack/metricbeat/module/panos/vpn/vpn_types.go b/x-pack/metricbeat/module/panos/vpn/vpn_types.go new file mode 100644 index 00000000000..236a291a908 --- /dev/null +++ b/x-pack/metricbeat/module/panos/vpn/vpn_types.go @@ -0,0 +1,94 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package vpn + +// GlobalProtect sesssions +type GPSessionsResponse struct { + Status string `xml:"status,attr"` + Result GPSessionsResult `xml:"result"` +} + +type GPSessionsResult struct { + Sessions []GPSession `xml:"entry"` +} + +type GPSession struct { + Domain string `xml:"domain"` + IsLocal string `xml:"islocal"` + Username string `xml:"username"` + PrimaryUsername string `xml:"primary-username"` + RegionForConfig string `xml:"region-for-config"` + SourceRegion string `xml:"source-region"` + Computer string `xml:"computer"` + Client string `xml:"client"` + VPNType string `xml:"vpn-type"` + HostID string `xml:"host-id"` + AppVersion string `xml:"app-version"` + VirtualIP string `xml:"virtual-ip"` + VirtualIPv6 string `xml:"virtual-ipv6"` + PublicIP string `xml:"public-ip"` + PublicIPv6 string `xml:"public-ipv6"` + TunnelType string `xml:"tunnel-type"` + PublicConnectionIPv6 string `xml:"public-connection-ipv6"` + ClientIP string `xml:"client-ip"` + LoginTime string `xml:"login-time"` + LoginTimeUTC string `xml:"login-time-utc"` + Lifetime string `xml:"lifetime"` + RequestLogin string `xml:"request-login"` + RequestGetConfig string `xml:"request-getconfig"` + RequestSSLVPNConnect string `xml:"request-sslvpnconnect"` +} + +// GlobalProtect gateway stats + +type GPStatsResponse struct { + Status string `xml:"status,attr"` + Result GPStatsResult `xml:"result"` +} + +type GPStatsResult struct { + Gateways []GPGateway `xml:"Gateway"` + TotalCurrentUsers int `xml:"TotalCurrentUsers"` + TotalPreviousUsers int `xml:"TotalPreviousUsers"` +} + +type GPGateway struct { + Name string `xml:"name"` + CurrentUsers int `xml:"CurrentUsers"` + PreviousUsers int `xml:"PreviousUsers"` +} + +// IPSec tunnels + +type TunnelsResponse struct { + Status string `xml:"status,attr"` + Result TunnelsResult `xml:"result"` +} + +type TunnelsResult struct { + Entries []TunnelsEntry `xml:"entries>entry"` + NTun int `xml:"ntun"` +} + +type TunnelsEntry struct { + ID int `xml:"id"` + Name string `xml:"name"` + GW string `xml:"gw"` + TSiIP string `xml:"TSi_ip"` + TSiPrefix int `xml:"TSi_prefix"` + TSiProto int `xml:"TSi_proto"` + TSiPort int `xml:"TSi_port"` + TSrIP string `xml:"TSr_ip"` + TSrPrefix int `xml:"TSr_prefix"` + TSrProto int `xml:"TSr_proto"` + TSrPort int `xml:"TSr_port"` + Proto string `xml:"proto"` + Mode string `xml:"mode"` + DH string `xml:"dh"` + Enc string `xml:"enc"` + Hash string `xml:"hash"` + Life int `xml:"life"` + KB int `xml:"kb"` +} diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panos.yml.disabled index 6eb4b9c30cd..9ad01318984 100644 --- a/x-pack/metricbeat/modules.d/panos.yml.disabled +++ b/x-pack/metricbeat/modules.d/panos.yml.disabled @@ -2,26 +2,8 @@ # Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html - module: panos - metricsets: - - "bgp_peers" - - "certificates" - - "fans" - - "filesystem" - - "globalprotect_sessions" - - "globalprotect_stats" - - "ha_interfaces" - - "licenses" - - "logical" - - "power" - - "power" - - "system" - - "temperature" - - "tunnels" - + metricsets: ["licenses"] enabled: false period: 10s - host_ip: "127.0.0.1" - apiKey: "" - apiDebugMode: false - + hosts: ["localhost"] From c9f2bec67cc4a9bec9d62ee21031f7cfd39ad204 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sat, 7 Sep 2024 15:29:39 -0400 Subject: [PATCH 15/32] more cleanup --- .../module/panos/system/types.go.old | 60 ------------------- x-pack/metricbeat/module/panos/vpn/vpn.go | 2 +- .../metricbeat/modules.d/panos.yml.disabled | 12 +++- 3 files changed, 11 insertions(+), 63 deletions(-) delete mode 100644 x-pack/metricbeat/module/panos/system/types.go.old diff --git a/x-pack/metricbeat/module/panos/system/types.go.old b/x-pack/metricbeat/module/panos/system/types.go.old deleted file mode 100644 index 6b1505dd66f..00000000000 --- a/x-pack/metricbeat/module/panos/system/types.go.old +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package system - -type Response struct { - Status string `xml:"status,attr"` - Result string `xml:"result"` -} - -type SystemLoad struct { - one_minute float64 - five_minute float64 - fifteen_minute float64 -} - -type Uptime struct { - Days int - Hours string -} - -type SystemInfo struct { - Uptime Uptime - UserCount int - LoadAverage SystemLoad -} - -type TaskInfo struct { - Total int - Running int - Sleeping int - Stopped int - Zombie int -} - -type CPUInfo struct { - User float64 - System float64 - Nice float64 - Idle float64 - Wait float64 - Hi float64 - SystemInt float64 - Steal float64 -} - -type MemoryInfo struct { - Total float64 - Free float64 - Used float64 - BufferCache float64 -} - -type SwapInfo struct { - Total float64 - Free float64 - Used float64 - Available float64 -} diff --git a/x-pack/metricbeat/module/panos/vpn/vpn.go b/x-pack/metricbeat/module/panos/vpn/vpn.go index 903f579cfd9..e3f428bbf58 100644 --- a/x-pack/metricbeat/module/panos/vpn/vpn.go +++ b/x-pack/metricbeat/module/panos/vpn/vpn.go @@ -94,7 +94,7 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { ipsecTunnelsEvents, err := getIPSecTunnelEvents(m) if err != nil { - m.logger.Error("Error get GlobalProtect stats events: %s", err) + m.logger.Error("Error get IPSec Tunnel events: %s", err) errs = append(errs, err.Error()) } diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panos.yml.disabled index 9ad01318984..b6ff7d630fe 100644 --- a/x-pack/metricbeat/modules.d/panos.yml.disabled +++ b/x-pack/metricbeat/modules.d/panos.yml.disabled @@ -2,8 +2,16 @@ # Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html - module: panos - metricsets: ["licenses"] + metricsets: + - "interfaces" + - "system" + - "routing" + - "vpn" + enabled: false period: 10s - hosts: ["localhost"] + host_ip: "127.0.0.1" + apiKey: "" + apiDebugMode: false + From 0438c2f997ccfaeb479996c47335333a64c781bf Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sat, 7 Sep 2024 16:44:12 -0400 Subject: [PATCH 16/32] cleanup field names --- .../module/panos/interfaces/ha_interfaces.go | 14 +- .../module/panos/routing/bgp_peers.go | 72 ++++---- .../module/panos/system/_meta/fields.yml | 161 +++++++++++++++++- .../module/panos/system/certificates.go | 22 +-- x-pack/metricbeat/module/panos/system/fans.go | 10 +- .../module/panos/system/filesystem.go | 12 +- .../metricbeat/module/panos/system/license.go | 14 +- .../metricbeat/module/panos/system/power.go | 12 +- .../module/panos/system/resources.go | 12 +- .../module/panos/system/system_types.go | 9 +- .../metricbeat/module/panos/system/thermal.go | 12 +- .../module/panos/vpn/gp_sessions.go | 48 +++--- .../metricbeat/module/panos/vpn/gp_stats.go | 10 +- x-pack/metricbeat/module/panos/vpn/tunnels.go | 36 ++-- x-pack/metricbeat/modules.d/panos.yml | 16 ++ .../metricbeat/modules.d/panos.yml.disabled | 17 -- 16 files changed, 323 insertions(+), 154 deletions(-) create mode 100644 x-pack/metricbeat/modules.d/panos.yml delete mode 100644 x-pack/metricbeat/modules.d/panos.yml.disabled diff --git a/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go index d105cd6b23a..90b16d747ca 100644 --- a/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go +++ b/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go @@ -124,13 +124,13 @@ func makeLinkMonitoringEvents(m *MetricSet, links HALinkMonitoring) []mb.Event { for _, group := range links.Groups { for _, interface_entry := range group.Interface { event = mb.Event{MetricSetFields: mapstr.M{ - "ha.link_monitoring.enabled": links.Enabled, - "ha.llink_monitoring.failure_condition": links.FailureCondition, - "ha.llink_monitoring.group.name": group.Name, - "ha.llink_monitoring.group.enabled": group.Enabled, - "ha.llink_monitoring.group.failure_condition": group.FailureCondition, - "ha.llink_monitoring.group.interface.name": interface_entry.Name, - "ha.llink_monitoring.group.interface.status": interface_entry.Status, + "ha.link_monitoring.enabled": links.Enabled, + "ha.link_monitoring.failure_condition": links.FailureCondition, + "ha.link_monitoring.group.name": group.Name, + "ha.link_monitoring.group.enabled": group.Enabled, + "ha.link_monitoring.group.failure_condition": group.FailureCondition, + "ha.link_monitoring.group.interface.name": interface_entry.Name, + "ha.link_monitoring.group.interface.status": interface_entry.Status, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/routing/bgp_peers.go b/x-pack/metricbeat/module/panos/routing/bgp_peers.go index c9c78be9779..3e17c954cfd 100644 --- a/x-pack/metricbeat/module/panos/routing/bgp_peers.go +++ b/x-pack/metricbeat/module/panos/routing/bgp_peers.go @@ -45,42 +45,42 @@ func formatBGPEvents(m *MetricSet, entries []BGPEntry) []mb.Event { for _, entry := range entries { event := mb.Event{MetricSetFields: mapstr.M{ - "bgp_peer_name": entry.Peer, - "virtual_router": entry.Vr, - "bgp_peer_group": entry.PeerGroup, - "bgp_peer_router_id": entry.PeerRouterID, - "remote_as_asn": entry.RemoteAS, - "status": entry.Status, - "status_duration": entry.StatusDuration, - "password_set": entry.PasswordSet, - "passive": entry.Passive, - "multi_hop_ttl": entry.MultiHopTTL, - "peer_address": entry.PeerAddress, - "local_address": entry.LocalAddress, - "reflector_client": entry.ReflectorClient, - "same_confederation": entry.SameConfederation, - "aggregate_confed_as": entry.AggregateConfedAS, - "peering_type": entry.PeeringType, - "connect_retry_interval": entry.ConnectRetryInterval, - "open_delay": entry.OpenDelay, - "idle_hold": entry.IdleHold, - "prefix_limit": entry.PrefixLimit, - "holdtime": entry.Holdtime, - "holdtime_config": entry.HoldtimeConfig, - "keepalive": entry.Keepalive, - "keepalive_config": entry.KeepaliveConfig, - "msg_update_in": entry.MsgUpdateIn, - "msg_update_out": entry.MsgUpdateOut, - "msg_total_in": entry.MsgTotalIn, - "msg_total_out": entry.MsgTotalOut, - "last_update_age": entry.LastUpdateAge, - "last_error": entry.LastError, - "status_flap_counts": entry.StatusFlapCounts, - "established_counts": entry.EstablishedCounts, - "orf_entry_received": entry.ORFEntryReceived, - "nexthop_self": entry.NexthopSelf, - "nexthop_thirdparty": entry.NexthopThirdparty, - "nexthop_peer": entry.NexthopPeer, + "bgp.peer_name": entry.Peer, + "bgp.virtual_router": entry.Vr, + "bgp.peer_group": entry.PeerGroup, + "bgp.peer_router_id": entry.PeerRouterID, + "bgp.remote_as_asn": entry.RemoteAS, + "bgp.status": entry.Status, + "bgp.status_duration": entry.StatusDuration, + "bgp.password_set": entry.PasswordSet, + "bgp.passive": entry.Passive, + "bgp.ulti_hop_ttl": entry.MultiHopTTL, + "bgp.peer_address": entry.PeerAddress, + "bgp.local_address": entry.LocalAddress, + "bgp.reflector_client": entry.ReflectorClient, + "bgp.same_confederation": entry.SameConfederation, + "bgp.aggregate_confed_as": entry.AggregateConfedAS, + "bgp.peering_type": entry.PeeringType, + "bgp.connect_retry_interval": entry.ConnectRetryInterval, + "bgp.open_delay": entry.OpenDelay, + "bgp.idle_hold": entry.IdleHold, + "bgp.prefix_limit": entry.PrefixLimit, + "bgp.holdtime": entry.Holdtime, + "bgp.holdtime_config": entry.HoldtimeConfig, + "bgp.keepalive": entry.Keepalive, + "bgp.keepalive_config": entry.KeepaliveConfig, + "bgp.msg_update_in": entry.MsgUpdateIn, + "bgp.msg_update_out": entry.MsgUpdateOut, + "bgp.msg_total_in": entry.MsgTotalIn, + "bgp.msg_total_out": entry.MsgTotalOut, + "bgp.last_update_age": entry.LastUpdateAge, + "bgp.last_error": entry.LastError, + "bgp.status_flap_counts": entry.StatusFlapCounts, + "bgp.established_counts": entry.EstablishedCounts, + "bgp.orf_entry_received": entry.ORFEntryReceived, + "bgp.nexthop_self": entry.NexthopSelf, + "bgp.nexthop_thirdparty": entry.NexthopThirdparty, + "bgp.nexthop_peer": entry.NexthopPeer, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/system/_meta/fields.yml b/x-pack/metricbeat/module/panos/system/_meta/fields.yml index 018e44d5abc..ac331d7bcd3 100644 --- a/x-pack/metricbeat/module/panos/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panos/system/_meta/fields.yml @@ -9,9 +9,13 @@ description: > Uptime in days - name: uptime.hours - type: keyword + type: integer + description: > + Hours component of uptime + - name: uptime.minutes + type: integer description: > - Uptime in hours + Minutes component of uptime - name: user_count type: integer description: > @@ -112,3 +116,156 @@ type: float description: > Available swap space + - name: license.feature + type: keyword + description: Feature licensed + - name: license.description + type: text + description: Description field + - name: license.serial + type: keyword + description: Serial number of license + - name: license.issued + type: date + description: Issued date field + - name: license.expires + type: date + description: Expires date field + - name: license.expired + type: boolean + description: Expired field + - name: license.auth_code + type: keyword + description: Auth code field + - name: filesystem.name + type: keyword + description: > + Filesystem name + - name: filesystem.size + type: keyword + description: > + Size, including units, e,g 9.5G. + - name: filesystem.used + type: keyword + description: > + Amount used, including units, e.g. 4.0G + - name: filesystem.available + type: keyword + description: > + Disk space available, including units, e.g. 5.5G + - name: filesystem.use_percent + type: keyword + description: > + Percent of filesystem used + - name: filesystem.mounted + type: keyword + description: > + Filesystem mount point + - name: fan.slot_number + type: integer + description: > + The number of the hardware slot + - name: fan.description + type: keyword + description: > + The description of the fan + - name: fan.alarm + type: boollean + description: > + Is there an alarm status of the fan + - name: fan.rpm + type: integer + description: > + The speed of the fan in RPM + - name: fan.min_rpm + type: integer + description: > + The minimum speed of the fan in RPM + - name: thermal.slot_number + type: integer + description: Slot number field + - name: thermal.description + type: text + description: Description field + - name: thermal.alarm + type: boolean + description: Alarm field + - name: thermal.degrees_celsius + type: float + description: Degrees Celsius field + - name: thermal.minimum_temp + type: float + description: Minimum temperature field + - name: thermal.maximum_temp + type: float + description: Maximum temperature field + - name: power.slot_number + type: keyword + description: Slot number field + - name: power.description + type: text + description: Description field + - name: power.alarm + type: boolean + description: Indicates if alarm is active + - name: power.volts + type: float + description: Current Volts + - name: power.minimum_volts + type: float + description: Minimum volts recorded + - name: power.maximum_volts + type: float + description: Maximum volts recorded + - name: issuer + type: keyword + description: > + issuer field + + - name: certificate.issuer_subject_hash + type: keyword + description: > + issuer_subject_hash field + + - name: certificate.issuer_key_hash + type: keyword + description: > + issuer_key_hash field + + - name: certificate.db_type + type: keyword + description: > + db_type field + + - name: certificate.db_exp_date + type: keyword + description: > + expiration date, format: 310329235959Z(Mar 29 23:59:59 2031 GMT) + + - name: certificate.db_rev_date + type: keyword + description: > + db_rev_date field + + - name: certificate.db_serial_no + type: keyword + description: > + db_serial_no field + + - name: certificate.db_file + type: keyword + description: > + db_file field + + - name: certificate.db_name + type: keyword + description: > + db_name field + + - name: certificate.db_status + type: keyword + description: > + db_status field + + + diff --git a/x-pack/metricbeat/module/panos/system/certificates.go b/x-pack/metricbeat/module/panos/system/certificates.go index 36b5572e0ea..ca81bfcc916 100644 --- a/x-pack/metricbeat/module/panos/system/certificates.go +++ b/x-pack/metricbeat/module/panos/system/certificates.go @@ -44,17 +44,17 @@ func formatCertificateEvents(m *MetricSet, input string) []mb.Event { for _, certificate := range certificates { event := mb.Event{ MetricSetFields: mapstr.M{ - "cert_name": certificate.CertName, - "issuer": certificate.Issuer, - "issuer_subject_hash": certificate.IssuerSubjectHash, - "issuer_key_hash": certificate.IssuerKeyHash, - "db_type": certificate.DBType, - "db_exp_date": certificate.DBExpDate, - "db_rev_date": certificate.DBRevDate, - "db_serial_no": certificate.DBSerialNo, - "db_file": certificate.DBFile, - "db_name": certificate.DBName, - "db_status": certificate.DBStatus, + "certificate.name": certificate.CertName, + "certificate.issuer": certificate.Issuer, + "certificate.issuer_subject_hash": certificate.IssuerSubjectHash, + "certificate.issuer_key_hash": certificate.IssuerKeyHash, + "certificate.db_type": certificate.DBType, + "certificate.db_exp_date": certificate.DBExpDate, + "certificate.db_rev_date": certificate.DBRevDate, + "certificate.db_serial_no": certificate.DBSerialNo, + "certificate.db_file": certificate.DBFile, + "certificate.db_name": certificate.DBName, + "certificate.db_status": certificate.DBStatus, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/system/fans.go b/x-pack/metricbeat/module/panos/system/fans.go index 3b1dca2e93b..3e04299b2f3 100644 --- a/x-pack/metricbeat/module/panos/system/fans.go +++ b/x-pack/metricbeat/module/panos/system/fans.go @@ -42,11 +42,11 @@ func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { for _, entry := range slot.Entries { log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) event = mb.Event{MetricSetFields: mapstr.M{ - "slot_number": entry.Slot, - "description": entry.Description, - "alarm": entry.Alarm, - "rpm": entry.RPMs, - "min_rpm": entry.Min, + "fan.slot_number": entry.Slot, + "fan.description": entry.Description, + "fan.alarm": entry.Alarm, + "fan.rpm": entry.RPMs, + "fan.min_rpm": entry.Min, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/system/filesystem.go b/x-pack/metricbeat/module/panos/system/filesystem.go index a9017242235..4adc63c3dc9 100644 --- a/x-pack/metricbeat/module/panos/system/filesystem.go +++ b/x-pack/metricbeat/module/panos/system/filesystem.go @@ -77,12 +77,12 @@ func formatFilesytemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { for _, filesystem := range filesystems { event := mb.Event{MetricSetFields: mapstr.M{ - "name": filesystem.Name, - "size": filesystem.Size, - "used": filesystem.Used, - "available": filesystem.Avail, - "use_percent": filesystem.UsePerc, - "mounted": filesystem.Mounted, + "filesystem.name": filesystem.Name, + "filesystem.size": filesystem.Size, + "filesystem.used": filesystem.Used, + "filesystem.available": filesystem.Avail, + "filesystem.use_percent": filesystem.UsePerc, + "filesystem.mounted": filesystem.Mounted, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/system/license.go b/x-pack/metricbeat/module/panos/system/license.go index c6c5425b58a..d12f03b8c1e 100644 --- a/x-pack/metricbeat/module/panos/system/license.go +++ b/x-pack/metricbeat/module/panos/system/license.go @@ -41,13 +41,13 @@ func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { for _, license := range licenses { event := mb.Event{MetricSetFields: mapstr.M{ - "feature": license.Feature, - "description": license.Description, - "serial": license.Serial, - "issued": license.Issued, - "expires": license.Expires, - "expired": license.Expired, - "auth_code": license.AuthCode, + "license.feature": license.Feature, + "license.escription": license.Description, + "license.serial": license.Serial, + "license.issued": license.Issued, + "license.expires": license.Expires, + "license.expired": license.Expired, + "license.auth_code": license.AuthCode, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/system/power.go b/x-pack/metricbeat/module/panos/system/power.go index 35b6f4ef047..d5a4aa8487d 100644 --- a/x-pack/metricbeat/module/panos/system/power.go +++ b/x-pack/metricbeat/module/panos/system/power.go @@ -44,12 +44,12 @@ func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) event = mb.Event{MetricSetFields: mapstr.M{ - "slot_number": entry.Slot, - "description": entry.Description, - "alarm": entry.Alarm, - "volts": entry.Volts, - "minimum_volts": entry.MinimumVolts, - "maximum_volts": entry.MaximumVolts, + "power.slot_number": entry.Slot, + "power.description": entry.Description, + "power.alarm": entry.Alarm, + "power.volts": entry.Volts, + "power.minimum_volts": entry.MinimumVolts, + "power.maximum_volts": entry.MaximumVolts, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/system/resources.go b/x-pack/metricbeat/module/panos/system/resources.go index c3d5955c7b7..1ad18bb92bd 100644 --- a/x-pack/metricbeat/module/panos/system/resources.go +++ b/x-pack/metricbeat/module/panos/system/resources.go @@ -116,13 +116,23 @@ func formatResourceEvents(m *MetricSet, input string) []mb.Event { return events } +func convertUptime(uptime string) (int, int) { + // 07:51 + hourstr := strings.Split(uptime, ":") + hours := parseInt(hourstr[0]) + minutes := parseInt(hourstr[1]) + + return hours, minutes +} + func parseSystemInfo(line string) SystemInfo { // top - 07:51:37 up 108 days, 1:38, 0 users, load average: 5.52, 5.79, 5.99 re := regexp.MustCompile(`\s+`) normal := re.ReplaceAllString(line, " ") fields := strings.Split(normal, " ") + upHours, upMinutes := convertUptime(fields[6]) - uptime := Uptime{parseInt(fields[4]), fields[6]} + uptime := Uptime{parseInt(fields[4]), upHours, upMinutes} loadAverage := strings.Split(normal, ": ")[1] loadAverageValues := strings.Split(loadAverage, ", ") diff --git a/x-pack/metricbeat/module/panos/system/system_types.go b/x-pack/metricbeat/module/panos/system/system_types.go index 9c3a6468f20..d130b9a2e75 100644 --- a/x-pack/metricbeat/module/panos/system/system_types.go +++ b/x-pack/metricbeat/module/panos/system/system_types.go @@ -4,7 +4,9 @@ package system -import "encoding/xml" +import ( + "encoding/xml" +) // system resources type ResourceResponse struct { @@ -19,8 +21,9 @@ type SystemLoad struct { } type Uptime struct { - Days int - Hours string + Days int + Hours int + Minutes int } type SystemInfo struct { diff --git a/x-pack/metricbeat/module/panos/system/thermal.go b/x-pack/metricbeat/module/panos/system/thermal.go index 6a89eeb5130..2ab4f6e805a 100644 --- a/x-pack/metricbeat/module/panos/system/thermal.go +++ b/x-pack/metricbeat/module/panos/system/thermal.go @@ -45,12 +45,12 @@ func formatThermalEvents(m *MetricSet, response *ThermalResponse) []mb.Event { log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) event = mb.Event{MetricSetFields: mapstr.M{ - "slot_number": entry.Slot, - "description": entry.Description, - "alarm": entry.Alarm, - "degress_celsius": entry.DegreesCelsius, - "minimum_temp": entry.MinimumTemp, - "maximum_temp": entry.MaximumTemp, + "thermal.slot_number": entry.Slot, + "thermal.description": entry.Description, + "thermal.alarm": entry.Alarm, + "thermal.degress_celsius": entry.DegreesCelsius, + "thermal.minimum_temp": entry.MinimumTemp, + "thermal.maximum_temp": entry.MaximumTemp, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/vpn/gp_sessions.go b/x-pack/metricbeat/module/panos/vpn/gp_sessions.go index 7566f8f36a3..ea1b8c31b69 100644 --- a/x-pack/metricbeat/module/panos/vpn/gp_sessions.go +++ b/x-pack/metricbeat/module/panos/vpn/gp_sessions.go @@ -41,30 +41,30 @@ func formatGPSessionEvents(m *MetricSet, sessions []GPSession) []mb.Event { for _, session := range sessions { event := mb.Event{MetricSetFields: mapstr.M{ - "domain": session.Domain, - "is_local": session.IsLocal, - "username": session.Username, - "primary_username": session.PrimaryUsername, - "region_for_config": session.RegionForConfig, - "source_region": session.SourceRegion, - "computer": session.Computer, - "client": session.Client, - "vpn_type": session.VPNType, - "host_id": session.HostID, - "app_version": session.AppVersion, - "virtual_ip": session.VirtualIP, - "virtual_ipv6": session.VirtualIPv6, - "public_ip": session.PublicIP, - "public_ipv6": session.PublicIPv6, - "tunnel_type": session.TunnelType, - "public_connection_ipv6": session.PublicConnectionIPv6, - "client_ip": session.ClientIP, - "login_time": session.LoginTime, - "login_time_utc": session.LoginTimeUTC, - "lifetime": session.Lifetime, - "request_login": session.RequestLogin, - "request_get_config": session.RequestGetConfig, - "request_sslvpn_connect": session.RequestSSLVPNConnect, + "globalprotect.domain": session.Domain, + "globalprotect.is_local": session.IsLocal, + "globalprotect.username": session.Username, + "globalprotect.rimary_username": session.PrimaryUsername, + "globalprotect.region_for_config": session.RegionForConfig, + "globalprotect.ource_region": session.SourceRegion, + "globalprotect.computer": session.Computer, + "globalprotect.client": session.Client, + "globalprotect.vpn_type": session.VPNType, + "globalprotect.host_id": session.HostID, + "globalprotect.app_version": session.AppVersion, + "globalprotect.virtual_ip": session.VirtualIP, + "globalprotect.virtual_ipv6": session.VirtualIPv6, + "globalprotect.public_ip": session.PublicIP, + "globalprotect.public_ipv6": session.PublicIPv6, + "globalprotect.tunnel_type": session.TunnelType, + "globalprotect.public_connection_ipv6": session.PublicConnectionIPv6, + "globalprotect.lient_ip": session.ClientIP, + "globalprotect.login_time": session.LoginTime, + "globalprotect.login_time_utc": session.LoginTimeUTC, + "globalprotect.lifetime": session.Lifetime, + "globalprotect.request_login": session.RequestLogin, + "globalprotect.request_get_config": session.RequestGetConfig, + "globalprotect.request_sslvpn_connect": session.RequestSSLVPNConnect, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/vpn/gp_stats.go b/x-pack/metricbeat/module/panos/vpn/gp_stats.go index f211a6d3178..f7177fe3009 100644 --- a/x-pack/metricbeat/module/panos/vpn/gp_stats.go +++ b/x-pack/metricbeat/module/panos/vpn/gp_stats.go @@ -43,11 +43,11 @@ func formatGPStatsEvents(m *MetricSet, response GPStatsResponse) []mb.Event { for _, gateway := range response.Result.Gateways { event := mb.Event{MetricSetFields: mapstr.M{ - "gateway.name": gateway.Name, - "gateway.current_users": gateway.CurrentUsers, - "gateway.previous_users": gateway.PreviousUsers, - "total_current_users": totalCurrent, - "total_previous_users": totalPrevious, + "globalprotect.gateway.name": gateway.Name, + "globalprotect.gateway.current_users": gateway.CurrentUsers, + "globalprotect.gateway.previous_users": gateway.PreviousUsers, + "globalprotect.total_current_users": totalCurrent, + "globalprotect.total_previous_users": totalPrevious, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/module/panos/vpn/tunnels.go b/x-pack/metricbeat/module/panos/vpn/tunnels.go index 9ef6904d4a7..8dcb13a79ec 100644 --- a/x-pack/metricbeat/module/panos/vpn/tunnels.go +++ b/x-pack/metricbeat/module/panos/vpn/tunnels.go @@ -41,24 +41,24 @@ func getEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { for _, entry := range entries { event := mb.Event{MetricSetFields: mapstr.M{ - "id": entry.ID, - "name": entry.Name, - "gw": entry.GW, - "TSi_ip": entry.TSiIP, - "TSi_prefix": entry.TSiPrefix, - "TSi_proto": entry.TSiProto, - "TSi_port": entry.TSiPort, - "TSr_ip": entry.TSrIP, - "TSr_prefix": entry.TSrPrefix, - "TSr_proto": entry.TSrProto, - "TSr_port": entry.TSrPort, - "proto": entry.Proto, - "mode": entry.Mode, - "dh": entry.DH, - "enc": entry.Enc, - "hash": entry.Hash, - "life": entry.Life, - "kb": entry.KB, + "ipsec_tunnel.id": entry.ID, + "ipsec_tunnel.name": entry.Name, + "ipsec_tunnel.gw": entry.GW, + "ipsec_tunnel.TSi_ip": entry.TSiIP, + "ipsec_tunnel.TSi_prefix": entry.TSiPrefix, + "ipsec_tunnel.TSi_proto": entry.TSiProto, + "ipsec_tunnel.TSi_port": entry.TSiPort, + "ipsec_tunnel.TSr_ip": entry.TSrIP, + "ipsec_tunnel.TSr_prefix": entry.TSrPrefix, + "ipsec_tunnel.TSr_proto": entry.TSrProto, + "ipsec_tunnel.TSr_port": entry.TSrPort, + "ipsec_tunnel.proto": entry.Proto, + "ipsec_tunnel.mode": entry.Mode, + "ipsec_tunnel.dh": entry.DH, + "ipsec_tunnel.enc": entry.Enc, + "ipsec_tunnel.hash": entry.Hash, + "ipsec_tunnel.life": entry.Life, + "ipsec_tunnel.kb": entry.KB, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, diff --git a/x-pack/metricbeat/modules.d/panos.yml b/x-pack/metricbeat/modules.d/panos.yml new file mode 100644 index 00000000000..4e34741c7ed --- /dev/null +++ b/x-pack/metricbeat/modules.d/panos.yml @@ -0,0 +1,16 @@ +# Module: panos +# Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html + +- module: panos + metricsets: + - "interfaces" + - "system" + - "routing" + - "vpn" + enabled: true + period: 60s + host_ip: "10.200.99.13" + apiKey: "LUFRPT1VNFV2eXUvbUJTNUNaT2VwOHMxd0ViRG1VZDQ9NURkZDcvZ3kwYTZWbENJeVZlcFdUSDQ2NDBOVFpoRjJWck9Ic0R5YVRsMFdzRVhVRzlmUHdoUGdGckt1bFVlTw==" + apiDebugMode: false + + diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panos.yml.disabled deleted file mode 100644 index b6ff7d630fe..00000000000 --- a/x-pack/metricbeat/modules.d/panos.yml.disabled +++ /dev/null @@ -1,17 +0,0 @@ -# Module: panos -# Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html - -- module: panos - metricsets: - - "interfaces" - - "system" - - "routing" - - "vpn" - - enabled: false - period: 10s - host_ip: "127.0.0.1" - apiKey: "" - apiDebugMode: false - - From 2c37e9a74915bc33d028f0140b8aa938ae0dbbbe Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sat, 7 Sep 2024 16:44:54 -0400 Subject: [PATCH 17/32] remove yml --- x-pack/metricbeat/modules.d/panos.yml | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 x-pack/metricbeat/modules.d/panos.yml diff --git a/x-pack/metricbeat/modules.d/panos.yml b/x-pack/metricbeat/modules.d/panos.yml deleted file mode 100644 index 4e34741c7ed..00000000000 --- a/x-pack/metricbeat/modules.d/panos.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Module: panos -# Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html - -- module: panos - metricsets: - - "interfaces" - - "system" - - "routing" - - "vpn" - enabled: true - period: 60s - host_ip: "10.200.99.13" - apiKey: "LUFRPT1VNFV2eXUvbUJTNUNaT2VwOHMxd0ViRG1VZDQ9NURkZDcvZ3kwYTZWbENJeVZlcFdUSDQ2NDBOVFpoRjJWck9Ic0R5YVRsMFdzRVhVRzlmUHdoUGdGckt1bFVlTw==" - apiDebugMode: false - - From 20e1103e600f8ee3d2bc1cd7377603930a2af5ad Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Sat, 7 Sep 2024 16:51:26 -0400 Subject: [PATCH 18/32] panos.yml.disabled --- x-pack/metricbeat/modules.d/panos.yml.disabled | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 x-pack/metricbeat/modules.d/panos.yml.disabled diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panos.yml.disabled new file mode 100644 index 00000000000..b6ff7d630fe --- /dev/null +++ b/x-pack/metricbeat/modules.d/panos.yml.disabled @@ -0,0 +1,17 @@ +# Module: panos +# Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panos.html + +- module: panos + metricsets: + - "interfaces" + - "system" + - "routing" + - "vpn" + + enabled: false + period: 10s + host_ip: "127.0.0.1" + apiKey: "" + apiDebugMode: false + + From 80a6c2bda508af301a0952f721e24a957fababfb Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Mon, 9 Sep 2024 18:02:49 -0400 Subject: [PATCH 19/32] PR comment fixes --- x-pack/metricbeat/include/list.go | 10 +- x-pack/metricbeat/module/panos/fields.go | 23 - .../module/panos/interfaces/_meta/fields.yml | 10 - .../module/panos/interfaces/ha_interfaces.go | 149 ---- .../module/panos/routing/_meta/fields.yml | 10 - .../module/panos/system/certificates.go | 119 --- .../metricbeat/module/panos/system/license.go | 65 -- .../metricbeat/module/panos/system/power.go | 67 -- .../module/panos/system/resources.go | 241 ------ .../module/panos/vpn/_meta/fields.yml | 10 - .../module/panos/vpn/gp_sessions.go | 81 -- x-pack/metricbeat/module/panos/vpn/tunnels.go | 76 -- .../module/{panos => panw}/_meta/config.yml | 0 .../{panos => panw}/_meta/docs.asciidoc | 0 .../module/{panos => panw}/_meta/fields.yml | 0 .../_meta/testdata/bgp_peers.xml | 0 .../module/{panos => panw}/client.go | 23 +- .../module/{panos => panw}/config.go | 4 +- .../metricbeat/module/{panos => panw}/doc.go | 4 +- x-pack/metricbeat/module/panw/fields.go | 23 + .../interfaces/_meta/data.json | 0 .../interfaces/_meta/docs.asciidoc | 0 .../module/panw/interfaces/_meta/fields.yml | 334 ++++++++ .../module/panw/interfaces/ha_interfaces.go | 185 +++++ .../interfaces/ifnet_interfaces.go | 64 +- .../interfaces/interface_types.go | 2 +- .../{panos => panw}/interfaces/interfaces.go | 57 +- .../{panos => panw}/routing/_meta/data.json | 0 .../routing/_meta/docs.asciidoc | 0 .../module/panw/routing/_meta/fields.yml | 150 ++++ .../{panos => panw}/routing/bgp_peers.go | 8 +- .../module/{panos => panw}/routing/routing.go | 46 +- .../{panos => panw}/routing/routing_types.go | 0 .../{panos => panw}/system/_meta/data.json | 0 .../system/_meta/docs.asciidoc | 0 .../{panos => panw}/system/_meta/fields.yml | 79 +- .../module/panw/system/certificates.go | 152 ++++ .../module/{panos => panw}/system/fans.go | 53 +- .../{panos => panw}/system/filesystem.go | 73 +- .../metricbeat/module/panw/system/license.go | 72 ++ x-pack/metricbeat/module/panw/system/power.go | 72 ++ .../module/panw/system/resources.go | 323 ++++++++ .../module/{panos => panw}/system/system.go | 118 +-- .../{panos => panw}/system/system_types.go | 6 +- .../module/{panos => panw}/system/thermal.go | 36 +- x-pack/metricbeat/module/panw/util.go | 18 + .../{panos => panw}/vpn/_meta/data.json | 0 .../{panos => panw}/vpn/_meta/docs.asciidoc | 0 .../module/panw/vpn/_meta/fields.yml | 194 +++++ .../metricbeat/module/panw/vpn/gp_sessions.go | 87 +++ .../module/{panos => panw}/vpn/gp_stats.go | 35 +- x-pack/metricbeat/module/panw/vpn/tunnels.go | 83 ++ .../module/{panos => panw}/vpn/vpn.go | 69 +- .../module/{panos => panw}/vpn/vpn_types.go | 0 .../{panos.yml.disabled => panw.yml.disabled} | 0 x-pack/metricbeat/patch1.diff | 717 ++++++++++++++++++ x-pack/metricbeat/patch2.diff | 717 ++++++++++++++++++ x-pack/metricbeat/x.diff | 429 +++++++++++ 58 files changed, 3900 insertions(+), 1194 deletions(-) delete mode 100644 x-pack/metricbeat/module/panos/fields.go delete mode 100644 x-pack/metricbeat/module/panos/interfaces/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go delete mode 100644 x-pack/metricbeat/module/panos/routing/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/system/certificates.go delete mode 100644 x-pack/metricbeat/module/panos/system/license.go delete mode 100644 x-pack/metricbeat/module/panos/system/power.go delete mode 100644 x-pack/metricbeat/module/panos/system/resources.go delete mode 100644 x-pack/metricbeat/module/panos/vpn/_meta/fields.yml delete mode 100644 x-pack/metricbeat/module/panos/vpn/gp_sessions.go delete mode 100644 x-pack/metricbeat/module/panos/vpn/tunnels.go rename x-pack/metricbeat/module/{panos => panw}/_meta/config.yml (100%) rename x-pack/metricbeat/module/{panos => panw}/_meta/docs.asciidoc (100%) rename x-pack/metricbeat/module/{panos => panw}/_meta/fields.yml (100%) rename x-pack/metricbeat/module/{panos => panw}/_meta/testdata/bgp_peers.xml (100%) rename x-pack/metricbeat/module/{panos => panw}/client.go (62%) rename x-pack/metricbeat/module/{panos => panw}/config.go (95%) rename x-pack/metricbeat/module/{panos => panw}/doc.go (74%) create mode 100644 x-pack/metricbeat/module/panw/fields.go rename x-pack/metricbeat/module/{panos => panw}/interfaces/_meta/data.json (100%) rename x-pack/metricbeat/module/{panos => panw}/interfaces/_meta/docs.asciidoc (100%) create mode 100644 x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go rename x-pack/metricbeat/module/{panos => panw}/interfaces/ifnet_interfaces.go (65%) rename x-pack/metricbeat/module/{panos => panw}/interfaces/interface_types.go (99%) rename x-pack/metricbeat/module/{panos => panw}/interfaces/interfaces.go (71%) rename x-pack/metricbeat/module/{panos => panw}/routing/_meta/data.json (100%) rename x-pack/metricbeat/module/{panos => panw}/routing/_meta/docs.asciidoc (100%) create mode 100644 x-pack/metricbeat/module/panw/routing/_meta/fields.yml rename x-pack/metricbeat/module/{panos => panw}/routing/bgp_peers.go (93%) rename x-pack/metricbeat/module/{panos => panw}/routing/routing.go (71%) rename x-pack/metricbeat/module/{panos => panw}/routing/routing_types.go (100%) rename x-pack/metricbeat/module/{panos => panw}/system/_meta/data.json (100%) rename x-pack/metricbeat/module/{panos => panw}/system/_meta/docs.asciidoc (100%) rename x-pack/metricbeat/module/{panos => panw}/system/_meta/fields.yml (81%) create mode 100644 x-pack/metricbeat/module/panw/system/certificates.go rename x-pack/metricbeat/module/{panos => panw}/system/fans.go (51%) rename x-pack/metricbeat/module/{panos => panw}/system/filesystem.go (51%) create mode 100644 x-pack/metricbeat/module/panw/system/license.go create mode 100644 x-pack/metricbeat/module/panw/system/power.go create mode 100644 x-pack/metricbeat/module/panw/system/resources.go rename x-pack/metricbeat/module/{panos => panw}/system/system.go (52%) rename x-pack/metricbeat/module/{panos => panw}/system/system_types.go (98%) rename x-pack/metricbeat/module/{panos => panw}/system/thermal.go (63%) create mode 100644 x-pack/metricbeat/module/panw/util.go rename x-pack/metricbeat/module/{panos => panw}/vpn/_meta/data.json (100%) rename x-pack/metricbeat/module/{panos => panw}/vpn/_meta/docs.asciidoc (100%) create mode 100644 x-pack/metricbeat/module/panw/vpn/_meta/fields.yml create mode 100644 x-pack/metricbeat/module/panw/vpn/gp_sessions.go rename x-pack/metricbeat/module/{panos => panw}/vpn/gp_stats.go (60%) create mode 100644 x-pack/metricbeat/module/panw/vpn/tunnels.go rename x-pack/metricbeat/module/{panos => panw}/vpn/vpn.go (65%) rename x-pack/metricbeat/module/{panos => panw}/vpn/vpn_types.go (100%) rename x-pack/metricbeat/modules.d/{panos.yml.disabled => panw.yml.disabled} (100%) create mode 100644 x-pack/metricbeat/patch1.diff create mode 100644 x-pack/metricbeat/patch2.diff create mode 100644 x-pack/metricbeat/x.diff diff --git a/x-pack/metricbeat/include/list.go b/x-pack/metricbeat/include/list.go index 289874d1ba1..874adf93f0e 100644 --- a/x-pack/metricbeat/include/list.go +++ b/x-pack/metricbeat/include/list.go @@ -55,11 +55,11 @@ import ( _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/performance" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/sysmetric" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/oracle/tablespace" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/interfaces" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/routing" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/system" - _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos/vpn" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw/interfaces" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw/routing" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw/system" + _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw/vpn" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/collector" _ "github.com/elastic/beats/v7/x-pack/metricbeat/module/prometheus/remote_write" diff --git a/x-pack/metricbeat/module/panos/fields.go b/x-pack/metricbeat/module/panos/fields.go deleted file mode 100644 index f37a88966ce..00000000000 --- a/x-pack/metricbeat/module/panos/fields.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -// Code generated by beats/dev-tools/cmd/asset/asset.go - DO NOT EDIT. - -package panos - -import ( - "github.com/elastic/beats/v7/libbeat/asset" -) - -func init() { - if err := asset.SetFields("metricbeat", "panos", asset.ModuleFieldsPri, AssetPanos); err != nil { - panic(err) - } -} - -// AssetPanos returns asset data. -// This is the base64 encoded zlib format compressed contents of module/panos. -func AssetPanos() string { - return "eJzMl0uPmzAQx+/5FKO9b6Q97IVDpapqT23VQ3OOBjwkVsC2/EhKP31lnCeYRwmo9W0X5ff7D7bH5hUOVCWgUEizArDcFpTAS/33ywpAU0FoKIGULK4AGJlMc2W5FAl8WAFA+C2UkrmCVgA5p4KZpH70CgJLuuH9sJWiBHZaOnX+T4T5iLlHcWFJ55iRuT6KMf1oZr+MqC+MKL0Z5T4O/cJS1XXfj5DnQNVJatZ41mP343MABmmrei2d5WK3ROlt9H9Ut6mMpXKJslvkvqqdsrykNcPKRCv3y2dH+u8q39RQ4AJa3IZ3L52Oiye98pu4Db6aDeltJp2w8xX83ZUpaZB5TY97C4lsi0fSuKP1WxmV54XEZqwB9VeJDM5YX/gblFw4S8MZ3hfL8H7OMOZFLJfirT+GRXMwaystFvMthJ8eB+K6HGpJj147IR5b1JMBbivxjB6MYAoitVCGC3s4hJVKUXO3z5MhoAcj/JZlyuPt/8kEgdwTIFNu7RvHXDvh048NOOO3QVrVHQmUlhkZ07EVvL91asyXIKBHZBA8i0/AswmuajhxuwcEJQ23/EjglXDEwsUbpk/FWcetYGIqzwN/TnUaT8jjh9NEo+f1G/d8Tt8eNTuhpnD51E7ZoXW35R3H8cQERuZ2dAJLHUfAVLkHdr/vkkqpq56TZ4I2nDuB3CfNNc22lr9oohFKZzr6+gTlxhAboUxdnvtLHmb72ar9VqN9N2WQSw3BYQAFg7boess/oVpipj0XjMKsRzv7XI+Rzj7bY6R4RF5gOl+b/ngBxvQX9VGJJT7fHrH/8Iv1TwAAAP//L81TLA==" -} diff --git a/x-pack/metricbeat/module/panos/interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panos/interfaces/_meta/fields.yml deleted file mode 100644 index 18f6505eaf2..00000000000 --- a/x-pack/metricbeat/module/panos/interfaces/_meta/fields.yml +++ /dev/null @@ -1,10 +0,0 @@ -- name: interfaces - type: group - release: beta - description: > - interfaces - fields: - - name: example - type: keyword - description: > - Example field diff --git a/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go deleted file mode 100644 index 90b16d747ca..00000000000 --- a/x-pack/metricbeat/module/panos/interfaces/ha_interfaces.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package interfaces - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" -) - -func getHAInterfaceEvents(m *MetricSet) ([]mb.Event, error) { - query := "" - var response HAResponse - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - events := formatHAInterfaceEvents(m, response.Result) - - return events, nil - -} - -func formatHAInterfaceEvents(m *MetricSet, input HAResult) []mb.Event { - events := make([]mb.Event, 0, len(input.Group.LinkMonitoring.Groups)+1) - group := input.Group - - groupEvent := makeGroupEvent(m, input) - events = append(events, *groupEvent) - linkMonitorEvents := makeLinkMonitoringEvents(m, group.LinkMonitoring) - events = append(events, linkMonitorEvents...) - - return events -} - -func makeGroupEvent(m *MetricSet, input HAResult) *mb.Event { - group := input.Group - currentTime := time.Now() - event := mb.Event{MetricSetFields: mapstr.M{ - "ha.enabled": input.Enabled, - "ha.mode": group.Mode, - "ha.running_sync": group.RunningSync, - "ha.running_sync_enabled": group.RunningSyncEnabled, - "ha.local_info.version": group.LocalInfo.Version, - "ha.local_info.state": group.LocalInfo.State, - "ha.local_info.state_duration": group.LocalInfo.StateDuration, - "ha.local_info.mgmt_ip": group.LocalInfo.MgmtIP, - "ha.local_info.preemptive": group.LocalInfo.Preemptive, - "ha.local_info.mode": group.LocalInfo.Mode, - "ha.local_info.platform_model": group.LocalInfo.PlatformModel, - "ha.local_info.state_sync": group.LocalInfo.StateSync, - "ha.local_info.state_sync_type": group.LocalInfo.StateSyncType, - "ha.local_info.ha1_ipaddr": group.LocalInfo.HA1IPAddr, - "ha.local_info.ha1_macaddr": group.LocalInfo.HA1MACAddr, - "ha.local_info.ha1_port": group.LocalInfo.HA1Port, - "ha.local_info.ha1_backup_ipaddr": group.LocalInfo.HA1BackupIPAddr, - "ha.local_info.ha1_backup_macaddr": group.LocalInfo.HA1BackupMACAddr, - "ha.local_info.ha1_backup_port": group.LocalInfo.HA1BackupPort, - "ha.local_info.ha1_backup_gateway": group.LocalInfo.HA1BackupGateway, - "ha.local_info.ha2_ipaddr": group.LocalInfo.HA2IPAddr, - "ha.local_info.ha2_macaddr": group.LocalInfo.HA2MACAddr, - "ha.local_info.ha2_port": group.LocalInfo.HA2Port, - "ha.local_info.build_rel": group.LocalInfo.BuildRel, - "ha.local_info.url_version": group.LocalInfo.URLVersion, - "ha.local_info.app_version": group.LocalInfo.AppVersion, - "ha.local_info.iot_version": group.LocalInfo.IoTVersion, - "ha.local_info.av_version": group.LocalInfo.AVVersion, - "ha.local_info.threat_version": group.LocalInfo.ThreatVersion, - "ha.local_info.vpn_client_version": group.LocalInfo.VPNClientVersion, - "ha.local_info.gp_client_version": group.LocalInfo.GPClientVersion, - "ha.peer_info.conn_status": group.PeerInfo.ConnStatus, - "ha.peer_info.state": group.PeerInfo.State, - "ha.peer_info.state_duration": group.PeerInfo.StateDuration, - "ha.peer_info.mgmt_ip": group.PeerInfo.MgmtIP, - "ha.peer_info.preemptive": group.PeerInfo.Preemptive, - "ha.peer_info.mode": group.PeerInfo.Mode, - "ha.peer_info.platform_model": group.PeerInfo.PlatformModel, - "ha.peer_info.priority": group.PeerInfo.Priority, - "ha.peer_info.ha1_ipaddr": group.PeerInfo.HA1IPAddr, - "ha.peer_info.ha1_macaddr": group.PeerInfo.HA1MACAddr, - "ha.peer_info.ha1_backup_ipaddr": group.PeerInfo.HA1BackupIPAddr, - "ha.peer_info.ha1_backup_macaddr": group.PeerInfo.HA1BackupMACAddr, - "ha.peer_info.ha2_ipaddr": group.PeerInfo.HA2IPAddr, - "ha.peer_info.ha2_macaddr": group.PeerInfo.HA2MACAddr, - "ha.peer_info.conn_ha1.status": group.PeerInfo.ConnHA1.Status, - "ha.peer_info.conn_ha1.primary": group.PeerInfo.ConnHA1.Primary, - "ha.peer_info.conn_ha1.description": group.PeerInfo.ConnHA1.Desc, - "ha.peer_info.conn_ha2.status": group.PeerInfo.ConnHA2.Status, - "ha.peer_info.conn_ha2.primary": group.PeerInfo.ConnHA2.Primary, - "ha.peer_info.conn_ha2.description": group.PeerInfo.ConnHA2.Desc, - "ha.peer_info.conn_ha1_backup.status": group.PeerInfo.ConnHA1Backup.Status, - "ha.peer_info.conn_ha1_backup.description": group.PeerInfo.ConnHA1Backup.Desc, - "ha.link_monitoring.enabled": group.LinkMonitoring.Enabled, - }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - "@Timestamp": currentTime, - }, - } - - return &event -} - -func makeLinkMonitoringEvents(m *MetricSet, links HALinkMonitoring) []mb.Event { - events := make([]mb.Event, 0, len(links.Groups)) - currentTime := time.Now() - var event mb.Event - for _, group := range links.Groups { - for _, interface_entry := range group.Interface { - event = mb.Event{MetricSetFields: mapstr.M{ - "ha.link_monitoring.enabled": links.Enabled, - "ha.link_monitoring.failure_condition": links.FailureCondition, - "ha.link_monitoring.group.name": group.Name, - "ha.link_monitoring.group.enabled": group.Enabled, - "ha.link_monitoring.group.failure_condition": group.FailureCondition, - "ha.link_monitoring.group.interface.name": interface_entry.Name, - "ha.link_monitoring.group.interface.status": interface_entry.Status, - }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - "@Timestamp": currentTime, - }, - } - } - - events = append(events, event) - } - - return events -} diff --git a/x-pack/metricbeat/module/panos/routing/_meta/fields.yml b/x-pack/metricbeat/module/panos/routing/_meta/fields.yml deleted file mode 100644 index 9b001ae10e6..00000000000 --- a/x-pack/metricbeat/module/panos/routing/_meta/fields.yml +++ /dev/null @@ -1,10 +0,0 @@ -- name: routing - type: group - release: beta - description: > - routing - fields: - - name: example - type: keyword - description: > - Example field diff --git a/x-pack/metricbeat/module/panos/system/certificates.go b/x-pack/metricbeat/module/panos/system/certificates.go deleted file mode 100644 index ca81bfcc916..00000000000 --- a/x-pack/metricbeat/module/panos/system/certificates.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package system - -import ( - "encoding/xml" - "regexp" - "strings" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" -) - -func getCertificateEvents(m *MetricSet) ([]mb.Event, error) { - query := "" - var response CertificateResponse - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - events := formatCertificateEvents(m, response.Result) - - return events, nil -} - -func formatCertificateEvents(m *MetricSet, input string) []mb.Event { - currentTime := time.Now() - - certificates := parseCertificates(input) - events := make([]mb.Event, 0, len(certificates)) - - for _, certificate := range certificates { - event := mb.Event{ - MetricSetFields: mapstr.M{ - "certificate.name": certificate.CertName, - "certificate.issuer": certificate.Issuer, - "certificate.issuer_subject_hash": certificate.IssuerSubjectHash, - "certificate.issuer_key_hash": certificate.IssuerKeyHash, - "certificate.db_type": certificate.DBType, - "certificate.db_exp_date": certificate.DBExpDate, - "certificate.db_rev_date": certificate.DBRevDate, - "certificate.db_serial_no": certificate.DBSerialNo, - "certificate.db_file": certificate.DBFile, - "certificate.db_name": certificate.DBName, - "certificate.db_status": certificate.DBStatus, - }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - "@Timestamp": currentTime, - }} - - events = append(events, event) - } - - return events -} - -func parseCertificates(input string) []Certificate { - lines := strings.Split(input, "\n") - pattern := `^[0-9A-Fa-f]{1,40}:[0-9A-Fa-f]{40}([0-9A-Fa-f]{24})?$` - regex := regexp.MustCompile(pattern) - var certificates []Certificate - var currentSN Certificate - - for _, line := range lines { - line = strings.TrimSpace(line) - if regex.MatchString(line) { - if currentSN.CertName != "" { - certificates = append(certificates, currentSN) - currentSN = Certificate{} - } - currentSN.CertName = line - } else if strings.HasPrefix(line, "issuer:") { - currentSN.Issuer = strings.TrimPrefix(line, "issuer: ") - } else if strings.HasPrefix(line, "issuer-subjecthash:") { - currentSN.IssuerSubjectHash = strings.TrimPrefix(line, "issuer-subjecthash: ") - } else if strings.HasPrefix(line, "issuer-keyhash:") { - currentSN.IssuerKeyHash = strings.TrimPrefix(line, "issuer-keyhash: ") - if strings.HasPrefix(currentSN.IssuerKeyHash, "issuer-keyhash:") { - currentSN.IssuerKeyHash = "" - } - } else if strings.HasPrefix(line, "db-type:") { - currentSN.DBType = strings.TrimPrefix(line, "db-type: ") - } else if strings.HasPrefix(line, "db-exp-date:") { - currentSN.DBExpDate = strings.TrimPrefix(line, "db-exp-date: ") - } else if strings.HasPrefix(line, "db-rev-date:") { - currentSN.DBRevDate = strings.TrimPrefix(line, "db-rev-date: ") - } else if strings.HasPrefix(line, "db-serialno:") { - currentSN.DBSerialNo = strings.TrimPrefix(line, "db-serialno: ") - } else if strings.HasPrefix(line, "db-file:") { - currentSN.DBFile = strings.TrimPrefix(line, "db-file: ") - } else if strings.HasPrefix(line, "db-name:") { - currentSN.DBName = strings.TrimPrefix(line, "db-name: ") - } else if strings.HasPrefix(line, "db-status:") { - currentSN.DBStatus = strings.TrimPrefix(line, "db-status: ") - } - } - - if currentSN.Issuer != "" { - certificates = append(certificates, currentSN) - } - - return certificates -} diff --git a/x-pack/metricbeat/module/panos/system/license.go b/x-pack/metricbeat/module/panos/system/license.go deleted file mode 100644 index d12f03b8c1e..00000000000 --- a/x-pack/metricbeat/module/panos/system/license.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package system - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" -) - -func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { - query := "" - var response LicenseResponse - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - events := formatLicenseEvents(m, response.Result.Licenses) - - return events, nil - -} - -func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { - events := make([]mb.Event, 0, len(licenses)) - - currentTime := time.Now() - - for _, license := range licenses { - event := mb.Event{MetricSetFields: mapstr.M{ - "license.feature": license.Feature, - "license.escription": license.Description, - "license.serial": license.Serial, - "license.issued": license.Issued, - "license.expires": license.Expires, - "license.expired": license.Expired, - "license.auth_code": license.AuthCode, - }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - "@Timestamp": currentTime, - }} - - events = append(events, event) - } - - return events - -} diff --git a/x-pack/metricbeat/module/panos/system/power.go b/x-pack/metricbeat/module/panos/system/power.go deleted file mode 100644 index d5a4aa8487d..00000000000 --- a/x-pack/metricbeat/module/panos/system/power.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package system - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" -) - -func getPowerEvents(m *MetricSet) ([]mb.Event, error) { - - query := "" - var response PowerResponse - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - events := formatPowerEvents(m, &response) - - return events, nil -} - -func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { - log := m.Logger() - events := make([]mb.Event, 0, len(response.Result.Power.Slots)) - currentTime := time.Now() - var event mb.Event - for _, slot := range response.Result.Power.Slots { - for _, entry := range slot.Entries { - log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) - event = mb.Event{MetricSetFields: mapstr.M{ - - "power.slot_number": entry.Slot, - "power.description": entry.Description, - "power.alarm": entry.Alarm, - "power.volts": entry.Volts, - "power.minimum_volts": entry.MinimumVolts, - "power.maximum_volts": entry.MaximumVolts, - }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - "@Timestamp": currentTime, - }} - } - - events = append(events, event) - } - - return events -} diff --git a/x-pack/metricbeat/module/panos/system/resources.go b/x-pack/metricbeat/module/panos/system/resources.go deleted file mode 100644 index 1ad18bb92bd..00000000000 --- a/x-pack/metricbeat/module/panos/system/resources.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package system - -import ( - "encoding/xml" - "fmt" - "regexp" - "strings" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" -) - -func getResourceEvents(m *MetricSet) ([]mb.Event, error) { - var response ResourceResponse - query := "" - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - events := formatResourceEvents(m, response.Result) - - return events, nil -} - -/* -Output from the XML API call is the standard "top" output: - -top - 07:51:37 up 108 days, 1:38, 0 users, load average: 5.52, 5.79, 5.99 -Tasks: 189 total, 7 running, 182 sleeping, 0 stopped, 0 zombie -%Cpu(s): 73.0 us, 4.6 sy, 0.0 ni, 21.7 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st -MiB Mem : 5026.9 total, 414.2 free, 2541.5 used, 2071.1 buff/cache -MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem - - PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND - 5692 20 0 121504 8396 6644 R 94.4 0.2 155491:08 pan_task - 5695 20 0 121504 7840 6632 R 94.4 0.2 155491:01 pan_task - 5696 20 0 121504 8360 6816 R 94.4 0.2 155486:29 pan_task - 5699 20 0 121504 8132 6676 R 94.4 0.2 155236:17 pan_task - 5700 20 0 146304 18424 6780 R 88.9 0.4 155491:40 pan_task - -22360 nobody 20 0 459836 40592 10148 R 22.2 0.8 0:38.65 httpd - - 6374 17 -3 1078156 18272 9716 S 5.6 0.4 215:46.41 routed - -14227 20 0 18108 7184 2172 R 5.6 0.1 0:00.04 top - - 1 20 0 2532 696 656 S 0.0 0.0 3:48.14 init - 2 20 0 0 0 0 S 0.0 0.0 0:00.83 kthreadd -*/ -func formatResourceEvents(m *MetricSet, input string) []mb.Event { - currentTime := time.Now() - events := make([]mb.Event, 0, 1) - - // We only need the top 5 lines - lines := strings.Split(input, "\n") - lines = lines[:5] - - systemInfo := parseSystemInfo(lines[0]) - taskInfo := parseTaskInfo(lines[1]) - cpuInfo := parseCPUInfo(lines[2]) - memoryInfo := parseMemoryInfo(lines[3]) - swapInfo := parseSwapInfo(lines[4]) - - event := mb.Event{MetricSetFields: mapstr.M{ - "uptime.days": systemInfo.Uptime.Days, - "uptime.hours": systemInfo.Uptime.Hours, - "user_count": systemInfo.UserCount, - "load_average.1m": systemInfo.LoadAverage.one_minute, - "load_average.5m": systemInfo.LoadAverage.five_minute, - "load_average.15m": systemInfo.LoadAverage.fifteen_minute, - "tasks.total": taskInfo.Total, - "tasks.running": taskInfo.Running, - "tasks.sleeping": taskInfo.Sleeping, - "tasks.stopped": taskInfo.Stopped, - "tasks.zombie": taskInfo.Zombie, - "cpu.user": cpuInfo.User, - "cpu.system": cpuInfo.System, - "cpu.nice": cpuInfo.Nice, - "cpu.idle": cpuInfo.Idle, - "cpu.wait": cpuInfo.Wait, - "cpu.hi": cpuInfo.Hi, - "cpu.system_int": cpuInfo.SystemInt, - "cpu.steal": cpuInfo.Steal, - "memory.total": memoryInfo.Total, - "memory.free": memoryInfo.Free, - "memory.used": memoryInfo.Used, - "memory.buffer_cache": memoryInfo.BufferCache, - "swap.total": swapInfo.Total, - "swap.free": swapInfo.Free, - "swap.used": swapInfo.Used, - "swap.available": swapInfo.Available, - }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - "@Timestamp": currentTime, - }} - - events = append(events, event) - return events -} - -func convertUptime(uptime string) (int, int) { - // 07:51 - hourstr := strings.Split(uptime, ":") - hours := parseInt(hourstr[0]) - minutes := parseInt(hourstr[1]) - - return hours, minutes -} - -func parseSystemInfo(line string) SystemInfo { - // top - 07:51:37 up 108 days, 1:38, 0 users, load average: 5.52, 5.79, 5.99 - re := regexp.MustCompile(`\s+`) - normal := re.ReplaceAllString(line, " ") - fields := strings.Split(normal, " ") - upHours, upMinutes := convertUptime(fields[6]) - - uptime := Uptime{parseInt(fields[4]), upHours, upMinutes} - loadAverage := strings.Split(normal, ": ")[1] - loadAverageValues := strings.Split(loadAverage, ", ") - - users := fields[7] - var loadAverageFloat []float64 - for _, value := range loadAverageValues { - loadAverageFloat = append(loadAverageFloat, parseFloat(value)) - } - - SystemLoad := SystemLoad{loadAverageFloat[0], loadAverageFloat[1], loadAverageFloat[2]} - return SystemInfo{ - Uptime: uptime, - UserCount: parseInt(users), - LoadAverage: SystemLoad, - } -} - -func parseTaskInfo(line string) TaskInfo { - //Tasks: 189 total, 7 running, 182 sleeping, 0 stopped, 0 zombie - values := strings.Fields(line) - - total := parseInt(values[1]) - running := parseInt(values[3]) - sleeping := parseInt(values[5]) - stopped := parseInt(values[7]) - zombie := parseInt(values[9]) - - return TaskInfo{ - Total: total, - Running: running, - Sleeping: sleeping, - Stopped: stopped, - Zombie: zombie, - } -} - -func parseCPUInfo(line string) CPUInfo { - //%Cpu(s): 73.0 us, 4.6 sy, 0.0 ni, 21.7 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st - values := strings.Fields(line) - - user := parseFloat(values[1]) - system := parseFloat(values[3]) - nice := parseFloat(values[5]) - idle := parseFloat(values[7]) - wait := parseFloat(values[9]) - hi := parseFloat(values[11]) - systemInt := parseFloat(values[13]) - steal := parseFloat(values[15]) - - return CPUInfo{ - User: user, - System: system, - Nice: nice, - Idle: idle, - Wait: wait, - Hi: hi, - SystemInt: systemInt, - Steal: steal, - } -} - -func parseMemoryInfo(line string) MemoryInfo { - //MiB Mem : 5026.9 total, 414.2 free, 2541.5 used, 2071.1 buff/cache - values := strings.Fields(line) - - total := parseFloat(values[3]) - free := parseFloat(values[5]) - used := parseFloat(values[7]) - bufferCache := parseFloat(values[9]) - - return MemoryInfo{ - Total: total, - Free: free, - Used: used, - BufferCache: bufferCache, - } -} - -func parseSwapInfo(line string) SwapInfo { - //MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem - values := strings.Fields(line) - - total := parseFloat(values[2]) - free := parseFloat(values[4]) - used := parseFloat(values[6]) - available := parseFloat(values[8]) - - return SwapInfo{ - Total: total, - Free: free, - Used: used, - Available: available, - } -} - -func parseFloat(value string) float64 { - var result float64 - fmt.Sscanf(value, "%f", &result) - return result -} - -func parseInt(value string) int { - var result int - fmt.Sscanf(value, "%d", &result) - return result -} diff --git a/x-pack/metricbeat/module/panos/vpn/_meta/fields.yml b/x-pack/metricbeat/module/panos/vpn/_meta/fields.yml deleted file mode 100644 index bea23e35c83..00000000000 --- a/x-pack/metricbeat/module/panos/vpn/_meta/fields.yml +++ /dev/null @@ -1,10 +0,0 @@ -- name: vpn - type: group - release: beta - description: > - vpn - fields: - - name: example - type: keyword - description: > - Example field diff --git a/x-pack/metricbeat/module/panos/vpn/gp_sessions.go b/x-pack/metricbeat/module/panos/vpn/gp_sessions.go deleted file mode 100644 index ea1b8c31b69..00000000000 --- a/x-pack/metricbeat/module/panos/vpn/gp_sessions.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package vpn - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" -) - -func getGlobalProtectSessionEvents(m *MetricSet) ([]mb.Event, error) { - query := "" - var response GPSessionsResponse - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - events := formatGPSessionEvents(m, response.Result.Sessions) - - return events, nil - -} - -func formatGPSessionEvents(m *MetricSet, sessions []GPSession) []mb.Event { - events := make([]mb.Event, 0, len(sessions)) - - currentTime := time.Now() - - for _, session := range sessions { - event := mb.Event{MetricSetFields: mapstr.M{ - "globalprotect.domain": session.Domain, - "globalprotect.is_local": session.IsLocal, - "globalprotect.username": session.Username, - "globalprotect.rimary_username": session.PrimaryUsername, - "globalprotect.region_for_config": session.RegionForConfig, - "globalprotect.ource_region": session.SourceRegion, - "globalprotect.computer": session.Computer, - "globalprotect.client": session.Client, - "globalprotect.vpn_type": session.VPNType, - "globalprotect.host_id": session.HostID, - "globalprotect.app_version": session.AppVersion, - "globalprotect.virtual_ip": session.VirtualIP, - "globalprotect.virtual_ipv6": session.VirtualIPv6, - "globalprotect.public_ip": session.PublicIP, - "globalprotect.public_ipv6": session.PublicIPv6, - "globalprotect.tunnel_type": session.TunnelType, - "globalprotect.public_connection_ipv6": session.PublicConnectionIPv6, - "globalprotect.lient_ip": session.ClientIP, - "globalprotect.login_time": session.LoginTime, - "globalprotect.login_time_utc": session.LoginTimeUTC, - "globalprotect.lifetime": session.Lifetime, - "globalprotect.request_login": session.RequestLogin, - "globalprotect.request_get_config": session.RequestGetConfig, - "globalprotect.request_sslvpn_connect": session.RequestSSLVPNConnect, - }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - "@Timestamp": currentTime, - }} - - events = append(events, event) - } - - return events -} diff --git a/x-pack/metricbeat/module/panos/vpn/tunnels.go b/x-pack/metricbeat/module/panos/vpn/tunnels.go deleted file mode 100644 index 8dcb13a79ec..00000000000 --- a/x-pack/metricbeat/module/panos/vpn/tunnels.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License; -// you may not use this file except in compliance with the Elastic License. - -package vpn - -import ( - "encoding/xml" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" -) - -func getIPSecTunnelEvents(m *MetricSet) ([]mb.Event, error) { - query := "" - var response TunnelsResponse - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - err = xml.Unmarshal(output, &response) - if err != nil { - m.logger.Error("Error: %s", err) - return nil, err - } - - events := getEvents(m, response.Result.Entries) - - return events, nil - -} - -func getEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { - events := make([]mb.Event, 0, len(entries)) - - currentTime := time.Now() - - for _, entry := range entries { - event := mb.Event{MetricSetFields: mapstr.M{ - "ipsec_tunnel.id": entry.ID, - "ipsec_tunnel.name": entry.Name, - "ipsec_tunnel.gw": entry.GW, - "ipsec_tunnel.TSi_ip": entry.TSiIP, - "ipsec_tunnel.TSi_prefix": entry.TSiPrefix, - "ipsec_tunnel.TSi_proto": entry.TSiProto, - "ipsec_tunnel.TSi_port": entry.TSiPort, - "ipsec_tunnel.TSr_ip": entry.TSrIP, - "ipsec_tunnel.TSr_prefix": entry.TSrPrefix, - "ipsec_tunnel.TSr_proto": entry.TSrProto, - "ipsec_tunnel.TSr_port": entry.TSrPort, - "ipsec_tunnel.proto": entry.Proto, - "ipsec_tunnel.mode": entry.Mode, - "ipsec_tunnel.dh": entry.DH, - "ipsec_tunnel.enc": entry.Enc, - "ipsec_tunnel.hash": entry.Hash, - "ipsec_tunnel.life": entry.Life, - "ipsec_tunnel.kb": entry.KB, - }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - "@Timestamp": currentTime, - }} - - events = append(events, event) - } - - return events - -} diff --git a/x-pack/metricbeat/module/panos/_meta/config.yml b/x-pack/metricbeat/module/panw/_meta/config.yml similarity index 100% rename from x-pack/metricbeat/module/panos/_meta/config.yml rename to x-pack/metricbeat/module/panw/_meta/config.yml diff --git a/x-pack/metricbeat/module/panos/_meta/docs.asciidoc b/x-pack/metricbeat/module/panw/_meta/docs.asciidoc similarity index 100% rename from x-pack/metricbeat/module/panos/_meta/docs.asciidoc rename to x-pack/metricbeat/module/panw/_meta/docs.asciidoc diff --git a/x-pack/metricbeat/module/panos/_meta/fields.yml b/x-pack/metricbeat/module/panw/_meta/fields.yml similarity index 100% rename from x-pack/metricbeat/module/panos/_meta/fields.yml rename to x-pack/metricbeat/module/panw/_meta/fields.yml diff --git a/x-pack/metricbeat/module/panos/_meta/testdata/bgp_peers.xml b/x-pack/metricbeat/module/panw/_meta/testdata/bgp_peers.xml similarity index 100% rename from x-pack/metricbeat/module/panos/_meta/testdata/bgp_peers.xml rename to x-pack/metricbeat/module/panw/_meta/testdata/bgp_peers.xml diff --git a/x-pack/metricbeat/module/panos/client.go b/x-pack/metricbeat/module/panw/client.go similarity index 62% rename from x-pack/metricbeat/module/panos/client.go rename to x-pack/metricbeat/module/panw/client.go index a781b998716..866862516aa 100644 --- a/x-pack/metricbeat/module/panos/client.go +++ b/x-pack/metricbeat/module/panw/client.go @@ -2,44 +2,45 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package panos +package panw import ( "flag" + "fmt" "github.com/PaloAltoNetworks/pango" ) -// PanosClient interface with an Op function -type PanosClient interface { +// PanwClient interface with an Op function +type PanwClient interface { Op(req interface{}, vsys string, extras interface{}, ans interface{}) ([]byte, error) } -type PanosFirewallClient struct { +type PanwFirewallClient struct { pango.Firewall } -type PanosTestClient struct { +type PanwTestClient struct { } // Op is a mock function for testing that returns sample XML output based on the initial req parameter // XML output is stored in the testdata directory, one file per query string -func (c *PanosTestClient) Op(req interface{}, vsys string, extras, ans interface{}) ([]byte, error) { +func (c *PanwTestClient) Op(req interface{}, vsys string, extras, ans interface{}) ([]byte, error) { return nil, nil } -func GetPanosClient(config *Config) (PanosClient, error) { +func GetPanwClient(config *Config) (PanwClient, error) { // If running tests, return a test client if flag.Lookup("test.v") != nil { - return &PanosTestClient{}, nil + return &PanwTestClient{}, nil } firewall := pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} err := firewall.Initialize() if err != nil { - return nil, err + return nil, fmt.Errorf("error initializing firewall client: %w", err) } - // Instantiate PanosFirewallClient - return &PanosFirewallClient{Firewall: firewall}, nil + // Instantiate panwFirewallClient + return &PanwFirewallClient{Firewall: firewall}, nil } diff --git a/x-pack/metricbeat/module/panos/config.go b/x-pack/metricbeat/module/panw/config.go similarity index 95% rename from x-pack/metricbeat/module/panos/config.go rename to x-pack/metricbeat/module/panw/config.go index 1bf01ca12b2..aface5a6397 100644 --- a/x-pack/metricbeat/module/panos/config.go +++ b/x-pack/metricbeat/module/panw/config.go @@ -2,7 +2,7 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package panos +package panw import ( "errors" @@ -11,7 +11,7 @@ import ( ) const ( - ModuleName = "panos" + ModuleName = "panw" ) type Config struct { diff --git a/x-pack/metricbeat/module/panos/doc.go b/x-pack/metricbeat/module/panw/doc.go similarity index 74% rename from x-pack/metricbeat/module/panos/doc.go rename to x-pack/metricbeat/module/panw/doc.go index af2af1298ea..21f5ce0404f 100644 --- a/x-pack/metricbeat/module/panos/doc.go +++ b/x-pack/metricbeat/module/panw/doc.go @@ -2,5 +2,5 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -// Package panos is a Metricbeat module that contains MetricSets. -package panos +// Package panw is a Metricbeat module that contains MetricSets. +package panw diff --git a/x-pack/metricbeat/module/panw/fields.go b/x-pack/metricbeat/module/panw/fields.go new file mode 100644 index 00000000000..42650ff9eb1 --- /dev/null +++ b/x-pack/metricbeat/module/panw/fields.go @@ -0,0 +1,23 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +// Code generated by beats/dev-tools/cmd/asset/asset.go - DO NOT EDIT. + +package panw + +import ( + "github.com/elastic/beats/v7/libbeat/asset" +) + +func init() { + if err := asset.SetFields("metricbeat", "panw", asset.ModuleFieldsPri, AssetPanw); err != nil { + panic(err) + } +} + +// AssetPanw returns asset data. +// This is the base64 encoded zlib format compressed contents of module/panw. +func AssetPanw() string { + return "eJzMmstu4zYUhvd5ioNZtUBGmCT1wl4UCOaSDlAXg85MF90ItHRks5FIghc7ztMXFCVHlqlLZHpa7ZJI//dRPD4kjbyFR9wvQBDG1RWApjrHBbwpf35zBSAxR6JwASvU5AogRZVIKjTlbAG/XgGAexYKnpocrwAyinmqFuWf3gIjBb7E20vvBS5gLbkR1W88mccxzSjKNMqMJKgOf/Jl2qvtXl9enru86W2Vpg4+kUKU425ezucR9zsu09bfeuj2+ugCHfRk9JIbTdn6EkM/jf4fjVvtlcbiEsM+Se4btRGaFhilZK+8I7fls0b5upF/L0OBMjjJbXE33MiA4N9sHCS8EJwh08CzCtTnUFBmNAa0WLpAn0d1h19HoYwTbpgOp/KHKVYoS75C6Z+KnJM0JluUZI3RTeGFZzknba0B9O+cpFDF2lK4Afeihx1mF3OYgW+y/S/ichY3/RqaqEcVaa5JHq4Qvtk4YIdyKCE9eGkYO+6dZwq8VGIVPaigckRxIYc6e1hCcyGw3fnDOLjoQYVnXqyof10608Al9wgkwkS2cYT6JLz/8h2Msh+D1b7sSCAkT1Cpjo+C5Z8sZ+EMXPQIB0YT/wSca3BAw47qDRAQXFFNtwgWCVuSG3/DtFY07diuTLSyedC5WlrijlD/4jSRaPP6iRsakrchMt0RiW5XLI3QQ3UX047leKKB4pkebaCxYwmYCreB3e+7wILLfc/KMwHr1h2X3AfNJAar5U8ScQTSqI6+PgH5XWE6ArkyWWY3eSTZBBvtsoy23TSFjEtwDAWEpXAKOhw/dkRcYqZtLihBkh5s8LkeAw0+22OgZEtoTlbh2vR9HTiEz2mCTGGUIdFGTj7VfnKP13FpL6vxpJen8al3uB9efmgdmn00hZJ2VO+IgX0tn25siKvYXiRVynRUUUp0+yUf8T6Xj5a3jRgbPgkqO46kQ6SP7tnXofyDWnGeI2lPpoeWjgARozdxwtPJtXhv9AZsQA8sozm6hTuyv5iK8vSZQzCcBHvgij4HhH+lz3gNlCW5Se2hxTCq1TXg9Rrm0ewhqu8bsursgZOs7gtumC4XHp9ctI7gl+jdwwiv/jY5Se4DVY+uPcIhvctyFs0eRry6WKBMsGM7OEnyiwu07ecFBSez5NEpX33IyWzUt5tWwds734MGYZHKuY5d8wx3MP22weY3FBt82a9bXqfM0Loz6YVYmcYttVHWaodND5IT6T+ojmikpwaflSVKBMKgjAaliTZqjIoUfpHJ86IEYtogA2Xw55dlp0BBWRxcoqCMFqZ4lYx9hQXJQ1Ts15zrukC7l6Aa+GN2QzXtrNq7L6trzJDWElHFCeaKGv/2ZHBT+8GFwHsXMgJbTXussRDTmMuqcGwCSrelHcElT+dyXcJIruA7lIOFOmZzO6pQHe7HlKljnVWkn1lKE6JRAc2qfkgVkETTrX875phbnuuJlfreSGmX579shH8T4xh1gZ7Bqiu0jACJCZdpxzagYlbFeQ6zqs5jprvRSy7PP5Or8rSnu7xW2XjJCUpNs3L+3SlMxsqs/sFExxuiNqGVjsIn+j3i/jJudfBrvdJVbOHhfKrACR74JGLPOfYMl/IYS8ouZIOvIeOyIHoBdzfv7m7nt3ez+Wz+909LIuF2Drd3i9l8MZvD7bu7G3hYfvv5VfoSt4H1G6ETXqf7KiRmPKjQIXWCkT2qBJWxgRM8wn4JUAVOmaFy5x52etxhoMPl6Imrtt1WNJfaYP95chz7H/6zzb8BAAD//xyMzHA=" +} diff --git a/x-pack/metricbeat/module/panos/interfaces/_meta/data.json b/x-pack/metricbeat/module/panw/interfaces/_meta/data.json similarity index 100% rename from x-pack/metricbeat/module/panos/interfaces/_meta/data.json rename to x-pack/metricbeat/module/panw/interfaces/_meta/data.json diff --git a/x-pack/metricbeat/module/panos/interfaces/_meta/docs.asciidoc b/x-pack/metricbeat/module/panw/interfaces/_meta/docs.asciidoc similarity index 100% rename from x-pack/metricbeat/module/panos/interfaces/_meta/docs.asciidoc rename to x-pack/metricbeat/module/panw/interfaces/_meta/docs.asciidoc diff --git a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml new file mode 100644 index 00000000000..79963bfd5f5 --- /dev/null +++ b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml @@ -0,0 +1,334 @@ +- name: interfaces + type: group + release: beta + description: > + interfaces + fields: + - name: physical.name + type: keyword + description: > + Physical interface name + - name: physical.id + type: keyword + description: > + Physical interface ID + - name: physical.type + type: keyword + description: > + Physical interface type: + 0: "Ethernet interface", + 1: "Aggregate Ethernet (AE) interface", + 2: "High Availability (HA) interface", + 3: "VLAN interface", + 5: "Loopback interface", + 6: "Tunnel interface", + 10: "SD-WAN interface", + - name: physical.mac + type: keyword + description: > + Physical MAC address + - name: physical.speed + type: keyword + description: > + Physical interface speed + - name: physical.duplex + type: keyword + description: > + Duplex configuration, e.g., "full" or "half" + - name: physical.state + type: keyword + description: > + Physical interface state: up/down + - name: physical.mode + type: keyword + description: > + Physical interface mode, e.g., autoneg + - name: physical.full_state + type: keyword + description: > + Physical full state, speed/duplex/state, e.g., "1000/full/up" + - name: physical.ae_member + type: keyword + description: > + For aggregate interfaces, the member interfaces + - name: logical.name + type: keyword + description: > + Logical interface name + - name: logical.id + type: keyword + description: > + Logical interface ID + - name: logical.tag + type: integer + description: > + VLAN tag associated with this interface + - name: logical.vsys + type: integer + description: > + Logical virtual system + - name: logical.zone + type: keyword + description: > + Logical zone, e.g., "inside" or "outside" + - name: logical.fwd + type: keyword + description: > + Indicates if the interface is used for forwarding + - name: logical.ip + type: ip + description: > + Logical IP Address with subnet mask, e.g., 111.222.333.10/29 + - name: logical.addr + type: keyword + description: > + Used to store aditional static IP addresses + - name: logical.dyn_addr + type: keyword + description: > + Dynamic addresses, e.g., generated by DHCP + - name: logical.addr6 + type: keyword + description: > + Logical IPv6 address + # HA Interface fields + - name: ha.enabled + type: boolean + description: > + HA enabled + - name: ha.mode + type: keyword + description: > + HA mode, e.g., "active-active" or "active-passive" + - name: ha.running_sync + type: keyword + description: > + Indicates the sychronization status of the HA pair, e.g., "synchronized","not-synchronized","synchronizing" + - name: ha.running_sync_enabled + type: boolean + description: > + Indicates if running configuration synchronization is enabled + - name: ha.local_info.version + type: long + description: > + HA configuration info version + - name: ha.local_info.state + type: keyword + description: > + HA state of the local device, e.g., "active" or "passive" + - name: ha.local_info.state_duration + type: long + description: > + Duration in milliseconds of the current state + - name: ha.local_info.mgmt_ip + type: ip + description: > + HA local info management IP + - name: ha.local_info.preemptive + type: boolean + description: > + Indicates whether the firewall is configured to preemptively take over as the active unit in an HA setup + - name: ha.local_info.mode + type: keyword + description: > + HA mode, e.g., "active-active" or "active-passive" + - name: ha.local_info.platform_model + type: keyword + description: > + Platform model of the local device + - name: ha.local_info.state_sync + type: keyword + description: > + Status of HA synchronization, e.g., "complete" + - name: ha.local_info.state_sync_type + type: keyword + description: > + Type of interface used for HA synchronization + - name: ha.local_info.ha1_ipaddr + type: ip + description: > + IP Address of HA1 interface, used for heartbeat and management synchronization + - name: ha.local_info.ha1_macaddr + type: keyword + description: > + HA local info HA1 MAC address + - name: ha.local_info.ha1_port + type: keyword + description: > + Indicates which interface is used for HA1 traffic, e.g., "dedicated-ha1" + - name: ha.local_info.ha1_backup_ipaddr + type: ip + description: > + The backup IP address for the HA1 interface + - name: ha.local_info.ha1_backup_macaddr + type: keyword + description: > + HA local info HA1 backup MAC address + - name: ha.local_info.ha1_backup_port + type: keyword + description: > + HA local info HA1 backup port, e.g. "management" + - name: ha.local_info.ha1_backup_gateway + type: ip + description: > + Default gateway for the backup HA1 interface + - name: ha.local_info.ha2_ipaddr + type: ip + description: > + HA local info HA2 IP address + - name: ha.local_info.ha2_macaddr + type: keyword + description: > + HA local info HA2 MAC address + - name: ha.local_info.ha2_port + type: keyword + description: > + Indicates which interface is used for HA1 traffic, e.g., "dedicated-ha2" + - name: ha.local_info.build_rel + type: keyword + description: > + The PAN-OS software version running on the firewall + - name: ha.local_info.url_version + type: keyword + description: > + The version of the URL filtering database + - name: ha.local_info.app_version + type: keyword + description: > + The version of the application database + - name: ha.local_info.iot_version + type: keyword + description: > + HA local info IoT version + - name: ha.local_info.av_version + type: keyword + description: > + The version of the antivirus database + - name: ha.local_info.threat_version + type: keyword + description: > + HA local info threat version + - name: ha.local_info.vpn_client_version + type: keyword + description: > + Version of the VPN client (if installed) + - name: ha.local_info.gp_client_version + type: keyword + description: > + Version of the GlobalProtect client software + - name: ha.peer_info.conn_status + type: keyword + description: > + Overall status of the HA connections ("up" means all connections are operational) + - name: ha.peer_info.state + type: keyword + description: > + Current operational state of the peer firewall (passive means it is in standby mode and not handling traffic) + - name: ha.peer_info.state_duration + type: long + description: > + How long the peer has been in the current state + - name: ha.peer_info.mgmt_ip + type: ip + description: > + Management IP address of the peer firewall + - name: ha.peer_info.preemptive + type: boolean + description: > + Indicates if preemption is enabled on the peer firewall + - name: ha.peer_info.mode + type: keyword + description: > + HA mode configured on the peer firewall, e.g. "Active-Passive" + - name: ha.peer_info.platform_model + type: keyword + description: > + Model of the peer firewall + - name: ha.peer_info.priority + type: long + description: > + HA priority value of the peer firewall + - name: ha.peer_info.ha1_ipaddr + type: ip + description: > + IP address of the HA1 interface on the peer + - name: ha.peer_info.ha1_macaddr + type: keyword + description: > + HA1 MAC address of the peer + - name: ha.peer_info.ha1_backup_ipaddr + type: ip + description: > + HA peer info HA1 backup IP address + - name: ha.peer_info.ha1_backup_macaddr + type: keyword + description: > + HA peer info HA1 backup MAC address + - name: ha.peer_info.ha2_ipaddr + type: ip + description: > + HA peer info HA2 IP address + - name: ha.peer_info.ha2_macaddr + type: keyword + description: > + HA peer info HA2 MAC address + - name: ha.peer_info.conn_ha1.status + type: keyword + description: > + Peer HA1 connection status, e.g., "up" + - name: ha.peer_info.conn_ha1.primary + type: boolean + description: > + Specifies if the HA1 connection is primary + - name: ha.peer_info.conn_ha1.description + type: keyword + description: > + Description of the connection type ,e.g., "heartbeat status" + - name: ha.peer_info.conn_ha2.status + type: keyword + description: > + HA peer info connection HA2 status + - name: ha.peer_info.conn_ha2.primary + type: boolean + description: > + Specifies if the HA2 connection is primary + - name: ha.peer_info.conn_ha2.description + type: keyword + description: > + HA peer info connection HA2 description + - name: ha.peer_info.conn_ha1_backup.status + type: keyword + description: > + HA peer info connection HA1 backup status, e.g., "up" means it is operational + - name: ha.peer_info.conn_ha1_backup.description + type: keyword + description: > + HA peer info connection HA1 backup description + - name: ha.link_monitoring.enabled + type: boolean + description: > + Indicates if link monitoring is enabled + - name: ha.link_monitoring.failure_condition + type: keyword + description: > + Condition that triggers a link monitoring failure, e.g., "any" + - name: ha.link_monitoring.group.name + type: keyword + description: > + Name of the link monitoring group + - name: ha.link_monitoring.group.enabled + type: boolean + description: > + Indicates if the link monitoring group is enabled + - name: ha.link_monitoring.group.failure_condition + type: keyword + description: > + Condition that triggers a failure in the link monitoring group + - name: ha.link_monitoring.group.interface.name + type: keyword + description: > + Name of the interface in the link monitoring group + - name: ha.link_monitoring.group.interface.status + type: keyword + description: > + Status of the interface in the link monitoring group \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go new file mode 100644 index 00000000000..1ccc4514d56 --- /dev/null +++ b/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go @@ -0,0 +1,185 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package interfaces + +import ( + "encoding/xml" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +const haInterfaceQuery = "" + +var logger *logp.Logger + +func getHAInterfaceEvents(m *MetricSet) ([]mb.Event, error) { + // Set logger so all the parse functions have access + logger = m.logger + var response HAResponse + + output, err := m.client.Op(haInterfaceQuery, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, err + } + + events := formatHAInterfaceEvents(m, response.Result) + + return events, nil + +} + +func formatHAInterfaceEvents(m *MetricSet, input HAResult) []mb.Event { + events := make([]mb.Event, 0, len(input.Group.LinkMonitoring.Groups)+1) + group := input.Group + + groupEvent := makeGroupEvent(m, input) + events = append(events, *groupEvent) + linkMonitorEvents := makeLinkMonitoringEvents(m, group.LinkMonitoring) + events = append(events, linkMonitorEvents...) + + return events +} + +func makeGroupEvent(m *MetricSet, input HAResult) *mb.Event { + + group := input.Group + timestamp := time.Now() + linkMonitoringEnabled, err := panw.StringToBool(group.LinkMonitoring.Enabled) + if err != nil { + logger.Warn("Error converting LinkMonitoring.Enabled to boolean: %s", err) + } + enabled, err := panw.StringToBool(input.Enabled) + if err != nil { + logger.Warn("Error converting Enabled to boolean: %s", err) + } + syncEnabled, err := panw.StringToBool(group.RunningSyncEnabled) + if err != nil { + logger.Warn("Error converting RunningSyncEnabled to boolean: %s", err) + } + + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "ha.enabled": enabled, + "ha.mode": group.Mode, + "ha.running_sync": group.RunningSync, + "ha.running_sync_enabled": syncEnabled, + "ha.local_info.version": group.LocalInfo.Version, + "ha.local_info.state": group.LocalInfo.State, + "ha.local_info.state_duration": group.LocalInfo.StateDuration, + "ha.local_info.mgmt_ip": group.LocalInfo.MgmtIP, + "ha.local_info.preemptive": group.LocalInfo.Preemptive, + "ha.local_info.mode": group.LocalInfo.Mode, + "ha.local_info.platform_model": group.LocalInfo.PlatformModel, + "ha.local_info.state_sync": group.LocalInfo.StateSync, + "ha.local_info.state_sync_type": group.LocalInfo.StateSyncType, + "ha.local_info.ha1_ipaddr": group.LocalInfo.HA1IPAddr, + "ha.local_info.ha1_macaddr": group.LocalInfo.HA1MACAddr, + "ha.local_info.ha1_port": group.LocalInfo.HA1Port, + "ha.local_info.ha1_backup_ipaddr": group.LocalInfo.HA1BackupIPAddr, + "ha.local_info.ha1_backup_macaddr": group.LocalInfo.HA1BackupMACAddr, + "ha.local_info.ha1_backup_port": group.LocalInfo.HA1BackupPort, + "ha.local_info.ha1_backup_gateway": group.LocalInfo.HA1BackupGateway, + "ha.local_info.ha2_ipaddr": group.LocalInfo.HA2IPAddr, + "ha.local_info.ha2_macaddr": group.LocalInfo.HA2MACAddr, + "ha.local_info.ha2_port": group.LocalInfo.HA2Port, + "ha.local_info.build_rel": group.LocalInfo.BuildRel, + "ha.local_info.url_version": group.LocalInfo.URLVersion, + "ha.local_info.app_version": group.LocalInfo.AppVersion, + "ha.local_info.iot_version": group.LocalInfo.IoTVersion, + "ha.local_info.av_version": group.LocalInfo.AVVersion, + "ha.local_info.threat_version": group.LocalInfo.ThreatVersion, + "ha.local_info.vpn_client_version": group.LocalInfo.VPNClientVersion, + "ha.local_info.gp_client_version": group.LocalInfo.GPClientVersion, + "ha.peer_info.conn_status": group.PeerInfo.ConnStatus, + "ha.peer_info.state": group.PeerInfo.State, + "ha.peer_info.state_duration": group.PeerInfo.StateDuration, + "ha.peer_info.mgmt_ip": group.PeerInfo.MgmtIP, + "ha.peer_info.preemptive": group.PeerInfo.Preemptive, + "ha.peer_info.mode": group.PeerInfo.Mode, + "ha.peer_info.platform_model": group.PeerInfo.PlatformModel, + "ha.peer_info.priority": group.PeerInfo.Priority, + "ha.peer_info.ha1_ipaddr": group.PeerInfo.HA1IPAddr, + "ha.peer_info.ha1_macaddr": group.PeerInfo.HA1MACAddr, + "ha.peer_info.ha1_backup_ipaddr": group.PeerInfo.HA1BackupIPAddr, + "ha.peer_info.ha1_backup_macaddr": group.PeerInfo.HA1BackupMACAddr, + "ha.peer_info.ha2_ipaddr": group.PeerInfo.HA2IPAddr, + "ha.peer_info.ha2_macaddr": group.PeerInfo.HA2MACAddr, + "ha.peer_info.conn_ha1.status": group.PeerInfo.ConnHA1.Status, + "ha.peer_info.conn_ha1.primary": group.PeerInfo.ConnHA1.Primary, + "ha.peer_info.conn_ha1.description": group.PeerInfo.ConnHA1.Desc, + "ha.peer_info.conn_ha2.status": group.PeerInfo.ConnHA2.Status, + "ha.peer_info.conn_ha2.primary": group.PeerInfo.ConnHA2.Primary, + "ha.peer_info.conn_ha2.description": group.PeerInfo.ConnHA2.Desc, + "ha.peer_info.conn_ha1_backup.status": group.PeerInfo.ConnHA1Backup.Status, + "ha.peer_info.conn_ha1_backup.description": group.PeerInfo.ConnHA1Backup.Desc, + "ha.link_monitoring.enabled": linkMonitoringEnabled, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + }, + } + + return &event +} + +func makeLinkMonitoringEvents(m *MetricSet, links HALinkMonitoring) []mb.Event { + if len(links.Groups) == 0 { + return nil + } + + events := make([]mb.Event, 0, len(links.Groups)) + timestamp := time.Now() + var event mb.Event + for _, group := range links.Groups { + for _, interface_entry := range group.Interface { + linkEnabled, err := panw.StringToBool(links.Enabled) + if err != nil { + logger.Warn("Error converting links.Enabled to boolean: %s", err) + } + groupEnabled, err := panw.StringToBool(group.Enabled) + if err != nil { + logger.Warn("Error converting group.Enabled to boolean: %s", err) + } + + event = mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "ha.link_monitoring.enabled": linkEnabled, + "ha.link_monitoring.failure_condition": links.FailureCondition, + "ha.link_monitoring.group.name": group.Name, + "ha.link_monitoring.group.enabled": groupEnabled, + "ha.link_monitoring.group.failure_condition": group.FailureCondition, + "ha.link_monitoring.group.interface.name": interface_entry.Name, + "ha.link_monitoring.group.interface.status": interface_entry.Status, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + }, + } + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/interfaces/ifnet_interfaces.go b/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go similarity index 65% rename from x-pack/metricbeat/module/panos/interfaces/ifnet_interfaces.go rename to x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go index 525601352f3..69aaaa54398 100644 --- a/x-pack/metricbeat/module/panos/interfaces/ifnet_interfaces.go +++ b/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go @@ -23,11 +23,13 @@ var interfaceTypes = map[int]string{ 10: "SD-WAN interface", } +const IFNetInterfaceQuery = "all" + func getIFNetInterfaceEvents(m *MetricSet) ([]mb.Event, error) { - query := "all" + var response InterfaceResponse - output, err := m.client.Op(query, vsys, nil, nil) + output, err := m.client.Op(IFNetInterfaceQuery, vsys, nil, nil) if err != nil { m.logger.Error("Error: %s", err) return nil, err @@ -47,7 +49,7 @@ func getIFNetInterfaceEvents(m *MetricSet) ([]mb.Event, error) { func formatIFInterfaceEvents(m *MetricSet, input InterfaceResult) []mb.Event { events := make([]mb.Event, 0, len(input.HW.Entries)+len(input.Ifnet.Entries)) - currentTime := time.Now() + timestamp := time.Now() // First process the phyiscal interfaces for _, entry := range input.HW.Entries { @@ -59,25 +61,25 @@ func formatIFInterfaceEvents(m *MetricSet, input InterfaceResult) []mb.Event { members = entry.AEMember.Members } - event := mb.Event{MetricSetFields: mapstr.M{ - "name": entry.Name, - "id": entry.ID, - "type": iftype, - "mac": entry.MAC, - "speed": entry.Speed, - "duplex": entry.Duplex, - "state": entry.State, - "mode": entry.Mode, - "st": entry.ST, - "ae_member": members, - "logical": false, - }, + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "physical.name": entry.Name, + "physical.id": entry.ID, + "physical.type": iftype, + "physical.mac": entry.MAC, + "physical.speed": entry.Speed, + "physical.duplex": entry.Duplex, + "physical.state": entry.State, + "physical.mode": entry.Mode, + "physical.full_state": entry.ST, + "physical.ae_member": members, + }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, "host.ip": m.config.HostIp, "observer.vendor": "Palo Alto", "observer.type": "firewall", - "@Timestamp": currentTime, }, } @@ -86,25 +88,25 @@ func formatIFInterfaceEvents(m *MetricSet, input InterfaceResult) []mb.Event { // Now process the logical interfaces for _, entry := range input.Ifnet.Entries { - event := mb.Event{MetricSetFields: mapstr.M{ - "name": entry.Name, - "id": entry.ID, - "tag": entry.Tag, - "vsys": entry.Vsys, - "zone": entry.Zone, - "fwd": entry.Fwd, - "ip": entry.IP_CIDR, - "addr": entry.Addr, - "dyn_addr": entry.DynAddr, - "addr6": entry.Addr6, - "logical": true, - }, + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "logical.name": entry.Name, + "logical.id": entry.ID, + "logical.tag": entry.Tag, + "logical.vsys": entry.Vsys, + "logical.zone": entry.Zone, + "logical.fwd": entry.Fwd, + "logical.ip": entry.IP, + "logical.addr": entry.Addr, + "logical.dyn_addr": entry.DynAddr, + "logical.addr6": entry.Addr6, + }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, "host.ip": m.config.HostIp, "observer.vendor": "Palo Alto", "observer.type": "firewall", - "@Timestamp": currentTime, }} events = append(events, event) diff --git a/x-pack/metricbeat/module/panos/interfaces/interface_types.go b/x-pack/metricbeat/module/panw/interfaces/interface_types.go similarity index 99% rename from x-pack/metricbeat/module/panos/interfaces/interface_types.go rename to x-pack/metricbeat/module/panw/interfaces/interface_types.go index abca8bafe63..452702ada7d 100644 --- a/x-pack/metricbeat/module/panos/interfaces/interface_types.go +++ b/x-pack/metricbeat/module/panw/interfaces/interface_types.go @@ -41,7 +41,7 @@ type IFInterfaceEntry struct { Vsys int `xml:"vsys"` Zone string `xml:"zone"` Fwd string `xml:"fwd"` - IP_CIDR string `xml:"ip"` + IP string `xml:"ip"` Addr string `xml:"addr"` DynAddr string `xml:"dyn-addr"` Addr6 string `xml:"addr6"` diff --git a/x-pack/metricbeat/module/panos/interfaces/interfaces.go b/x-pack/metricbeat/module/panw/interfaces/interfaces.go similarity index 71% rename from x-pack/metricbeat/module/panos/interfaces/interfaces.go rename to x-pack/metricbeat/module/panw/interfaces/interfaces.go index a25501e1d8f..bfaa491c116 100644 --- a/x-pack/metricbeat/module/panos/interfaces/interfaces.go +++ b/x-pack/metricbeat/module/panw/interfaces/interfaces.go @@ -6,11 +6,11 @@ package interfaces import ( "errors" - "strings" + "fmt" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/logp" ) @@ -25,9 +25,9 @@ const ( // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - config *panos.Config + config *panw.Config logger *logp.Logger - client panos.PanosClient + client panw.PanwClient } // init registers the MetricSet with the central registry as soon as the program @@ -35,15 +35,15 @@ type MetricSet struct { // the MetricSet for each host is defined in the module's configuration. After the // MetricSet has been created then Fetch will begin to be called periodically. func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) + mb.Registry.MustAddMetricSet(panw.ModuleName, metricsetName, New) } // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos interfaces metricset is beta.") + cfgwarn.Beta("The panw interfaces metricset is beta.") - config, err := panos.NewConfig(base) + config, err := panw.NewConfig(base) if err != nil { return nil, err } @@ -51,7 +51,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { logger := logp.NewLogger(base.FullyQualifiedName()) //client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - client, err := panos.GetPanosClient(config) + client, err := panw.GetPanwClient(config) if err != nil { return nil, err } @@ -70,31 +70,32 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { func (m *MetricSet) Fetch(report mb.ReporterV2) error { // accumulate errs and report them all at the end so that we don't // stop processing events if one of the fetches fails - var errs []string - - intefaceEvents, err := getIFNetInterfaceEvents(m) - if err != nil { - m.logger.Error("Error get IFInterface events: %s", err) - errs = append(errs, err.Error()) + var errs []error + + eventFetchers := []struct { + name string + fn func(*MetricSet) ([]mb.Event, error) + }{ + {"ifnet interfaces", getIFNetInterfaceEvents}, + {"HA interfaces", getHAInterfaceEvents}, } - for _, event := range intefaceEvents { - report.Event(event) + for _, fetcher := range eventFetchers { + events, err := fetcher.fn(m) + if err != nil { + m.logger.Errorf("Error getting %s events: %s", fetcher.name, err) + errs = append(errs, err) + } else { + for _, event := range events { + report.Event(event) + } + } } - haEvents, err := getHAInterfaceEvents(m) - if err != nil { - m.logger.Error("Error get HAInterface events: %s", err) - errs = append(errs, err.Error()) + if len(errs) > 0 { + return fmt.Errorf("error while fetching vpn metrics: %w", errors.Join(errs...)) } - for _, event := range haEvents { - report.Event(event) - } + return nil - if len(errs) > 0 { - return errors.New(strings.Join(errs, "; ")) - } else { - return nil - } } diff --git a/x-pack/metricbeat/module/panos/routing/_meta/data.json b/x-pack/metricbeat/module/panw/routing/_meta/data.json similarity index 100% rename from x-pack/metricbeat/module/panos/routing/_meta/data.json rename to x-pack/metricbeat/module/panw/routing/_meta/data.json diff --git a/x-pack/metricbeat/module/panos/routing/_meta/docs.asciidoc b/x-pack/metricbeat/module/panw/routing/_meta/docs.asciidoc similarity index 100% rename from x-pack/metricbeat/module/panos/routing/_meta/docs.asciidoc rename to x-pack/metricbeat/module/panw/routing/_meta/docs.asciidoc diff --git a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml new file mode 100644 index 00000000000..20b53dc6895 --- /dev/null +++ b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml @@ -0,0 +1,150 @@ +- name: routing + type: group + release: beta + description: > + routing + fields: + - name: bgp.peer_name + type: keyword + description: > + BGP peer name + - name: bgp.virtual_router + type: keyword + description: > + BGP virtual router + - name: bgp.peer_group + type: keyword + description: > + BGP peer group + - name: bgp.peer_router_id + type: keyword + description: > + BGP peer router ID + - name: bgp.remote_as_asn + type: keyword + description: > + BGP remote AS ASN + - name: bgp.status + type: keyword + description: > + BGP status + - name: bgp.status_duration + type: long + description: > + BGP status duration + - name: bgp.password_set + type: boolean + description: > + BGP password set + - name: bgp.passive + type: boolean + description: > + BGP passive + - name: bgp.multi_hop_ttl + type: long + description: > + BGP multi-hop TTL + - name: bgp.peer_address + type: ip + description: > + BGP peer address + - name: bgp.local_address + type: ip + description: > + BGP local address + - name: bgp.reflector_client + type: boolean + description: > + BGP reflector client + - name: bgp.same_confederation + type: boolean + description: > + BGP same confederation + - name: bgp.aggregate_confed_as + type: boolean + description: > + BGP aggregate confederation AS + - name: bgp.peering_type + type: keyword + description: > + BGP peering type + - name: bgp.connect_retry_interval + type: long + description: > + BGP connect retry interval + - name: bgp.open_delay + type: long + description: > + BGP open delay + - name: bgp.idle_hold + type: long + description: > + BGP idle hold + - name: bgp.prefix_limit + type: long + description: > + BGP prefix limit + - name: bgp.holdtime + type: long + description: > + BGP holdtime + - name: bgp.holdtime_config + type: long + description: > + BGP holdtime config + - name: bgp.keepalive + type: long + description: > + BGP keepalive + - name: bgp.keepalive_config + type: long + description: > + BGP keepalive config + - name: bgp.msg_update_in + type: long + description: > + BGP message updates in + - name: bgp.msg_update_out + type: long + description: > + BGP message updates out + - name: bgp.msg_total_in + type: long + description: > + BGP total messages in + - name: bgp.msg_total_out + type: long + description: > + BGP total messages out + - name: bgp.last_update_age + type: long + description: > + BGP last update age + - name: bgp.last_error + type: keyword + description: > + BGP last error + - name: bgp.status_flap_counts + type: long + description: > + BGP status flap counts + - name: bgp.established_counts + type: long + description: > + BGP established counts + - name: bgp.orf_entry_received + type: long + description: > + BGP ORF entry received + - name: bgp.nexthop_self + type: boolean + description: > + BGP next-hop self + - name: bgp.nexthop_thirdparty + type: boolean + description: > + BGP next-hop third-party + - name: bgp.nexthop_peer + type: boolean + description: > + BGP next-hop peer \ No newline at end of file diff --git a/x-pack/metricbeat/module/panos/routing/bgp_peers.go b/x-pack/metricbeat/module/panw/routing/bgp_peers.go similarity index 93% rename from x-pack/metricbeat/module/panos/routing/bgp_peers.go rename to x-pack/metricbeat/module/panw/routing/bgp_peers.go index 3e17c954cfd..5d5c48862c9 100644 --- a/x-pack/metricbeat/module/panos/routing/bgp_peers.go +++ b/x-pack/metricbeat/module/panw/routing/bgp_peers.go @@ -12,8 +12,10 @@ import ( "github.com/elastic/elastic-agent-libs/mapstr" ) +const bgpPeersQuery = "" + func getBGPEvents(m *MetricSet) ([]mb.Event, error) { - query := "" + var response BGPResponse // Initialize the client @@ -22,7 +24,7 @@ func getBGPEvents(m *MetricSet) ([]mb.Event, error) { // return err // } - output, err := m.client.Op(query, vsys, nil, nil) + output, err := m.client.Op(bgpPeersQuery, vsys, nil, nil) if err != nil { m.logger.Error("Error calling API: %s", err) return nil, err @@ -54,7 +56,7 @@ func formatBGPEvents(m *MetricSet, entries []BGPEntry) []mb.Event { "bgp.status_duration": entry.StatusDuration, "bgp.password_set": entry.PasswordSet, "bgp.passive": entry.Passive, - "bgp.ulti_hop_ttl": entry.MultiHopTTL, + "bgp.multi_hop_ttl": entry.MultiHopTTL, "bgp.peer_address": entry.PeerAddress, "bgp.local_address": entry.LocalAddress, "bgp.reflector_client": entry.ReflectorClient, diff --git a/x-pack/metricbeat/module/panos/routing/routing.go b/x-pack/metricbeat/module/panw/routing/routing.go similarity index 71% rename from x-pack/metricbeat/module/panos/routing/routing.go rename to x-pack/metricbeat/module/panw/routing/routing.go index 33e7659eef5..1ba3904bc3f 100644 --- a/x-pack/metricbeat/module/panos/routing/routing.go +++ b/x-pack/metricbeat/module/panw/routing/routing.go @@ -6,11 +6,11 @@ package routing import ( "errors" - "strings" + "fmt" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/logp" ) @@ -25,9 +25,9 @@ const ( // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - config *panos.Config + config *panw.Config logger *logp.Logger - client panos.PanosClient + client panw.PanwClient } // init registers the MetricSet with the central registry as soon as the program @@ -35,22 +35,22 @@ type MetricSet struct { // the MetricSet for each host is defined in the module's configuration. After the // MetricSet has been created then Fetch will begin to be called periodically. func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) + mb.Registry.MustAddMetricSet(panw.ModuleName, metricsetName, New) } // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos routing metricset is beta.") + cfgwarn.Beta("The panw routing metricset is beta.") - config, err := panos.NewConfig(base) + config, err := panw.NewConfig(base) if err != nil { return nil, err } logger := logp.NewLogger(base.FullyQualifiedName()) - client, err := panos.GetPanosClient(config) + client, err := panw.GetPanwClient(config) if err != nil { return nil, err } @@ -69,21 +69,31 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { func (m *MetricSet) Fetch(report mb.ReporterV2) error { // accumulate errs and report them all at the end so that we don't // stop processing events if one of the fetches fails - var errs []string + var errs []error - bgpEvents, err := getBGPEvents(m) - if err != nil { - m.logger.Error("Error get BGP events: %s", err) - errs = append(errs, err.Error()) + eventFetchers := []struct { + name string + fn func(*MetricSet) ([]mb.Event, error) + }{ + {"bgp peers", getBGPEvents}, } - for _, event := range bgpEvents { - report.Event(event) + for _, fetcher := range eventFetchers { + events, err := fetcher.fn(m) + if err != nil { + m.logger.Errorf("Error getting %s events: %s", fetcher.name, err) + errs = append(errs, err) + } else { + for _, event := range events { + report.Event(event) + } + } } if len(errs) > 0 { - return errors.New(strings.Join(errs, "; ")) - } else { - return nil + return fmt.Errorf("error while fetching vpn metrics: %w", errors.Join(errs...)) } + + return nil + } diff --git a/x-pack/metricbeat/module/panos/routing/routing_types.go b/x-pack/metricbeat/module/panw/routing/routing_types.go similarity index 100% rename from x-pack/metricbeat/module/panos/routing/routing_types.go rename to x-pack/metricbeat/module/panw/routing/routing_types.go diff --git a/x-pack/metricbeat/module/panos/system/_meta/data.json b/x-pack/metricbeat/module/panw/system/_meta/data.json similarity index 100% rename from x-pack/metricbeat/module/panos/system/_meta/data.json rename to x-pack/metricbeat/module/panw/system/_meta/data.json diff --git a/x-pack/metricbeat/module/panos/system/_meta/docs.asciidoc b/x-pack/metricbeat/module/panw/system/_meta/docs.asciidoc similarity index 100% rename from x-pack/metricbeat/module/panos/system/_meta/docs.asciidoc rename to x-pack/metricbeat/module/panw/system/_meta/docs.asciidoc diff --git a/x-pack/metricbeat/module/panos/system/_meta/fields.yml b/x-pack/metricbeat/module/panw/system/_meta/fields.yml similarity index 81% rename from x-pack/metricbeat/module/panos/system/_meta/fields.yml rename to x-pack/metricbeat/module/panw/system/_meta/fields.yml index ac331d7bcd3..69dd48a622a 100644 --- a/x-pack/metricbeat/module/panos/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/system/_meta/fields.yml @@ -17,7 +17,7 @@ description: > Minutes component of uptime - name: user_count - type: integer + type: long description: > Number of users - name: load_average.1m @@ -33,23 +33,23 @@ description: > Load average in 15 minutes - name: tasks.total - type: integer + type: long description: > Total number of tasks - name: tasks.running - type: integer + type: long description: > Number of running tasks - name: tasks.sleeping - type: integer + type: long description: > Number of sleeping tasks - name: tasks.stopped - type: integer + type: long description: > Number of stopped tasks - name: tasks.zombie - type: integer + type: long description: > Number of zombie tasks - name: cpu.user @@ -118,25 +118,32 @@ Available swap space - name: license.feature type: keyword - description: Feature licensed + description: > + Feature licensed - name: license.description type: text - description: Description field + description: > + Description field - name: license.serial type: keyword - description: Serial number of license + description: > + Serial number of license - name: license.issued type: date - description: Issued date field + description: > + Issued date field - name: license.expires type: date - description: Expires date field + description: > + Expires date field - name: license.expired type: boolean - description: Expired field + description: > + Expired field - name: license.auth_code type: keyword - description: Auth code field + description: > + Auth code field - name: filesystem.name type: keyword description: > @@ -144,15 +151,15 @@ - name: filesystem.size type: keyword description: > - Size, including units, e,g 9.5G. + Size, including units, e.g., 9.5G. - name: filesystem.used type: keyword description: > - Amount used, including units, e.g. 4.0G + Amount used, including units, e.g., 4.0G - name: filesystem.available type: keyword description: > - Disk space available, including units, e.g. 5.5G + Disk space available, including units, e.g., 5.5G - name: filesystem.use_percent type: keyword description: > @@ -170,7 +177,7 @@ description: > The description of the fan - name: fan.alarm - type: boollean + type: boolean description: > Is there an alarm status of the fan - name: fan.rpm @@ -183,41 +190,53 @@ The minimum speed of the fan in RPM - name: thermal.slot_number type: integer - description: Slot number field + description: > + Slot number field - name: thermal.description type: text - description: Description field + description: > + Description field - name: thermal.alarm type: boolean - description: Alarm field + description: > + Alarm field - name: thermal.degrees_celsius type: float - description: Degrees Celsius field + description: > + Degrees Celsius field - name: thermal.minimum_temp type: float - description: Minimum temperature field + description: > + Minimum temperature field - name: thermal.maximum_temp type: float - description: Maximum temperature field + description: > + Maximum temperature field - name: power.slot_number type: keyword - description: Slot number field + description: > + Slot number field - name: power.description type: text - description: Description field + description: > + Description field - name: power.alarm type: boolean - description: Indicates if alarm is active + description: > + Indicates if alarm is active - name: power.volts type: float - description: Current Volts + description: > + Current Volts - name: power.minimum_volts type: float - description: Minimum volts recorded + description: > + Minimum volts recorded - name: power.maximum_volts type: float - description: Maximum volts recorded - - name: issuer + description: > + Maximum volts recorded + - name: certificate.issuer type: keyword description: > issuer field diff --git a/x-pack/metricbeat/module/panw/system/certificates.go b/x-pack/metricbeat/module/panw/system/certificates.go new file mode 100644 index 00000000000..1993421fd43 --- /dev/null +++ b/x-pack/metricbeat/module/panw/system/certificates.go @@ -0,0 +1,152 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "errors" + "fmt" + "regexp" + "strings" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +const certificatesQuery = "" + +func getCertificateEvents(m *MetricSet) ([]mb.Event, error) { + + var response CertificateResponse + + output, err := m.client.Op(certificatesQuery, vsys, nil, nil) + if err != nil { + return nil, fmt.Errorf("failed to execute query: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + + if response.Result == "" { + return nil, fmt.Errorf("empty result from XML response") + } + + events, err := formatCertificateEvents(m, response.Result) + if err != nil { + return nil, fmt.Errorf("failed to format certificate events: %w", err) + } + + return events, nil +} + +func formatCertificateEvents(m *MetricSet, input string) ([]mb.Event, error) { + timestamp := time.Now() + + certificates, err := parseCertificates(input) + if err != nil { + return nil, err + } + + events := make([]mb.Event, 0, len(certificates)) + + for _, certificate := range certificates { + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "certificate.name": certificate.CertName, + "certificate.issuer": certificate.Issuer, + "certificate.issuer_subject_hash": certificate.IssuerSubjectHash, + "certificate.issuer_key_hash": certificate.IssuerKeyHash, + "certificate.db_type": certificate.DBType, + "certificate.db_exp_date": certificate.DBExpDate, + "certificate.db_rev_date": certificate.DBRevDate, + "certificate.db_serial_no": certificate.DBSerialNo, + "certificate.db_file": certificate.DBFile, + "certificate.db_name": certificate.DBName, + "certificate.db_status": certificate.DBStatus, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + }, + } + + events = append(events, event) + } + + return events, nil +} + +const ( + issuerPrefix = "issuer: " + issuerSubjectHashPrefix = "issuer-subjecthash: " + issuerKeyHashPrefix = "issuer-keyhash: " + dbTypePrefix = "db-type: " + dbExpDatePrefix = "db-exp-date: " + dbRevDatePrefix = "db-rev-date: " + dbSerialNoPrefix = "db-serialno: " + dbFilePrefix = "db-file: " + dbNamePrefix = "db-name: " + dbStatusPrefix = "db-status: " +) + +func parseCertificates(input string) ([]Certificate, error) { + lines := strings.Split(input, "\n") + pattern := `^[0-9A-Fa-f]{1,40}:[0-9A-Fa-f]{40}([0-9A-Fa-f]{24})?$` + regex := regexp.MustCompile(pattern) + + certificates := make([]Certificate, 0) + var currentSN Certificate + + for _, line := range lines { + line = strings.TrimSpace(line) + switch { + case regex.MatchString(line): + if currentSN.CertName != "" { + certificates = append(certificates, currentSN) + currentSN = Certificate{} + } + currentSN.CertName = line + case strings.HasPrefix(line, issuerPrefix): + currentSN.Issuer = strings.TrimPrefix(line, issuerPrefix) + case strings.HasPrefix(line, issuerSubjectHashPrefix): + currentSN.IssuerSubjectHash = strings.TrimPrefix(line, issuerSubjectHashPrefix) + case strings.HasPrefix(line, issuerKeyHashPrefix): + currentSN.IssuerKeyHash = strings.TrimPrefix(line, issuerKeyHashPrefix) + if strings.HasPrefix(currentSN.IssuerKeyHash, issuerKeyHashPrefix) { + currentSN.IssuerKeyHash = "" + } + case strings.HasPrefix(line, dbTypePrefix): + currentSN.DBType = strings.TrimPrefix(line, dbTypePrefix) + case strings.HasPrefix(line, dbExpDatePrefix): + currentSN.DBExpDate = strings.TrimPrefix(line, dbExpDatePrefix) + case strings.HasPrefix(line, dbRevDatePrefix): + currentSN.DBRevDate = strings.TrimPrefix(line, dbRevDatePrefix) + case strings.HasPrefix(line, dbSerialNoPrefix): + currentSN.DBSerialNo = strings.TrimPrefix(line, dbSerialNoPrefix) + case strings.HasPrefix(line, dbFilePrefix): + currentSN.DBFile = strings.TrimPrefix(line, dbFilePrefix) + case strings.HasPrefix(line, dbNamePrefix): + currentSN.DBName = strings.TrimPrefix(line, dbNamePrefix) + case strings.HasPrefix(line, dbStatusPrefix): + currentSN.DBStatus = strings.TrimPrefix(line, dbStatusPrefix) + } + } + + if currentSN.CertName != "" { + certificates = append(certificates, currentSN) + } + + if len(certificates) == 0 { + return nil, errors.New("no valid certificates found") + } + + return certificates, nil +} diff --git a/x-pack/metricbeat/module/panos/system/fans.go b/x-pack/metricbeat/module/panw/system/fans.go similarity index 51% rename from x-pack/metricbeat/module/panos/system/fans.go rename to x-pack/metricbeat/module/panw/system/fans.go index 3e04299b2f3..5e333c6e182 100644 --- a/x-pack/metricbeat/module/panos/system/fans.go +++ b/x-pack/metricbeat/module/panw/system/fans.go @@ -6,58 +6,61 @@ package system import ( "encoding/xml" + "fmt" "time" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/elastic-agent-libs/mapstr" ) +const fansQuery = "" + func getFanEvents(m *MetricSet) ([]mb.Event, error) { - query := "" + var response FanResponse - output, err := m.client.Op(query, vsys, nil, nil) + output, err := m.client.Op(fansQuery, vsys, nil, nil) if err != nil { - m.logger.Error("Error: %s", err) - return nil, err + return nil, fmt.Errorf("error querying fan data: %w", err) } err = xml.Unmarshal(output, &response) if err != nil { - m.logger.Error("Error: %s", err) - return nil, err + return nil, fmt.Errorf("error unmarshaling fan data: %w", err) } - events := formatFanEvents(m, &response) - - return events, nil + return formatFanEvents(m, &response), nil } func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { - log := m.Logger() - events := make([]mb.Event, 0, len(response.Result.Fan.Slots)) - currentTime := time.Now() - var event mb.Event + if response == nil || len(response.Result.Fan.Slots) == 0 { + return nil + } + + events := make([]mb.Event, 0) + timestamp := time.Now() + for _, slot := range response.Result.Fan.Slots { for _, entry := range slot.Entries { - log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) - event = mb.Event{MetricSetFields: mapstr.M{ - "fan.slot_number": entry.Slot, - "fan.description": entry.Description, - "fan.alarm": entry.Alarm, - "fan.rpm": entry.RPMs, - "fan.min_rpm": entry.Min, - }, + m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "fan.slot_number": entry.Slot, + "fan.description": entry.Description, + "fan.alarm": entry.Alarm, + "fan.rpm": entry.RPMs, + "fan.min_rpm": entry.Min, + }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, "host.ip": m.config.HostIp, "observer.vendor": "Palo Alto", "observer.type": "firewall", - "@Timestamp": currentTime, - }} + }, + } + events = append(events, event) } - - events = append(events, event) } return events diff --git a/x-pack/metricbeat/module/panos/system/filesystem.go b/x-pack/metricbeat/module/panw/system/filesystem.go similarity index 51% rename from x-pack/metricbeat/module/panos/system/filesystem.go rename to x-pack/metricbeat/module/panw/system/filesystem.go index 4adc63c3dc9..43a35c87913 100644 --- a/x-pack/metricbeat/module/panos/system/filesystem.go +++ b/x-pack/metricbeat/module/panw/system/filesystem.go @@ -6,6 +6,7 @@ package system import ( "encoding/xml" + "fmt" "strings" "time" @@ -13,46 +14,46 @@ import ( "github.com/elastic/elastic-agent-libs/mapstr" ) +const filesystemQuery = "" + func getFilesystemEvents(m *MetricSet) ([]mb.Event, error) { - query := "" var response FilesystemResponse - output, err := m.client.Op(query, vsys, nil, nil) + output, err := m.client.Op(filesystemQuery, vsys, nil, nil) if err != nil { - m.logger.Error("Error: %s", err) - return nil, err + return nil, fmt.Errorf("error querying filesystem info: %w", err) + } + + if len(output) == 0 { + return nil, fmt.Errorf("received empty output from filesystem query") } err = xml.Unmarshal(output, &response) if err != nil { - m.logger.Error("Error: %s", err) - return nil, err + return nil, fmt.Errorf("error unmarshaling filesystem response: %w", err) } filesystems := getFilesystems(response.Result.Data) - events := formatFilesytemEvents(m, filesystems) + events := formatFilesystemEvents(m, filesystems) return events, nil } -/* -Result from the XML API call is basically linux df -h output: -Filesystem Size Used Avail Use% Mounted on -/dev/root 9.5G 4.0G 5.1G 44% / -none 2.5G 64K 2.5G 1% /dev -/dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg -/dev/sda6 7.6G 3.1G 4.2G 43% /opt/panrepo -tmpfs 2.5G 399M 2.1G 16% /dev/shm -cgroup_root 2.5G 0 2.5G 0% /cgroup -/dev/sda8 173G 63G 102G 39% /opt/panlogs -tmpfs 12M 44K 12M 1% /opt/pancfg/mgmt/ssl/private -*/ func getFilesystems(input string) []Filesystem { lines := strings.Split(input, "\n") filesystems := make([]Filesystem, 0) - // Skip the first line which is the header + // Skip the first line which is the header: + // + // Example: + // Result from the XML API call is basically a command in Linux distribution i.e., "df -h"'s output: + // + // Filesystem Size Used Avail Use% Mounted on + // /dev/root 9.5G 4.0G 5.1G 44% / + // none 2.5G 64K 2.5G 1% /dev + // /dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg + // for _, line := range lines[1:] { fields := strings.Fields(line) if len(fields) == 6 { @@ -70,31 +71,35 @@ func getFilesystems(input string) []Filesystem { return filesystems } -func formatFilesytemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { - events := make([]mb.Event, 0, len(filesystems)) +func formatFilesystemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { + if len(filesystems) == 0 { + return nil + } - currentTime := time.Now() + events := make([]mb.Event, 0, len(filesystems)) + timestamp := time.Now() for _, filesystem := range filesystems { - event := mb.Event{MetricSetFields: mapstr.M{ - "filesystem.name": filesystem.Name, - "filesystem.size": filesystem.Size, - "filesystem.used": filesystem.Used, - "filesystem.available": filesystem.Avail, - "filesystem.use_percent": filesystem.UsePerc, - "filesystem.mounted": filesystem.Mounted, - }, + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "filesystem.name": filesystem.Name, + "filesystem.size": filesystem.Size, + "filesystem.used": filesystem.Used, + "filesystem.available": filesystem.Avail, + "filesystem.use_percent": filesystem.UsePerc, + "filesystem.mounted": filesystem.Mounted, + }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, "host.ip": m.config.HostIp, "observer.vendor": "Palo Alto", "observer.type": "firewall", - "@Timestamp": currentTime, - }} + }, + } events = append(events, event) } return events - } diff --git a/x-pack/metricbeat/module/panw/system/license.go b/x-pack/metricbeat/module/panw/system/license.go new file mode 100644 index 00000000000..8130ccfac07 --- /dev/null +++ b/x-pack/metricbeat/module/panw/system/license.go @@ -0,0 +1,72 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +const licenseQuery = "" + +func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { + + var response LicenseResponse + + output, err := m.client.Op(licenseQuery, vsys, nil, nil) + if err != nil { + return nil, fmt.Errorf("failed to execute query: %w", err) + } + + if len(output) == 0 { + return nil, fmt.Errorf("empty response from PanOS") + } + + err = xml.Unmarshal(output, &response) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + + if len(response.Result.Licenses) == 0 { + m.logger.Warn("No licenses found in the response") + return nil, nil + } + + return formatLicenseEvents(m, response.Result.Licenses), nil +} + +func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { + events := make([]mb.Event, 0, len(licenses)) + timestamp := time.Now() + + for _, license := range licenses { + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "license.feature": license.Feature, + "license.description": license.Description, // Fixed typo + "license.serial": license.Serial, + "license.issued": license.Issued, + "license.expires": license.Expires, + "license.expired": license.Expired, + "license.auth_code": license.AuthCode, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + }, + } + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panw/system/power.go b/x-pack/metricbeat/module/panw/system/power.go new file mode 100644 index 00000000000..f9ead893383 --- /dev/null +++ b/x-pack/metricbeat/module/panw/system/power.go @@ -0,0 +1,72 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +const powerQuery = "" + +// getPowerEvents retrieves power-related events from a PAN-OS device. +func getPowerEvents(m *MetricSet) ([]mb.Event, error) { + + var response PowerResponse + + output, err := m.client.Op(powerQuery, vsys, nil, nil) + if err != nil { + return nil, fmt.Errorf("failed to execute operation: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + + if len(response.Result.Power.Slots) == 0 { + m.logger.Warn("No power events found in the response") + return nil, nil + } + + events := formatPowerEvents(m, &response) + + return events, nil +} + +func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { + events := make([]mb.Event, 0) + timestamp := time.Now() + + for _, slot := range response.Result.Power.Slots { + for _, entry := range slot.Entries { + m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "power.slot_number": entry.Slot, + "power.description": entry.Description, + "power.alarm": entry.Alarm, + "power.volts": entry.Volts, + "power.minimum_volts": entry.MinimumVolts, + "power.maximum_volts": entry.MaximumVolts, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + }, + } + events = append(events, event) + } + } + + return events +} diff --git a/x-pack/metricbeat/module/panw/system/resources.go b/x-pack/metricbeat/module/panw/system/resources.go new file mode 100644 index 00000000000..8feed62155f --- /dev/null +++ b/x-pack/metricbeat/module/panw/system/resources.go @@ -0,0 +1,323 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package system + +import ( + "encoding/xml" + "fmt" + "regexp" + "strconv" + "strings" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/logp" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +const resourceQuery = "" + +var logger *logp.Logger + +func getResourceEvents(m *MetricSet) ([]mb.Event, error) { + // Set logger so all the parse functions have access + logger = m.logger + + var response ResourceResponse + output, err := m.client.Op(resourceQuery, vsys, nil, &response) + if err != nil { + return nil, fmt.Errorf("failed to execute operation: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + + events := formatResourceEvents(m, response.Result) + + return events, nil +} + +/* +Output from the XML API call is the standard "top" output: + +top - 07:51:37 up 108 days, 1:38, 0 users, load average: 5.52, 5.79, 5.99 +Tasks: 189 total, 7 running, 182 sleeping, 0 stopped, 0 zombie +%Cpu(s): 73.0 us, 4.6 sy, 0.0 ni, 21.7 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st +MiB Mem : 5026.9 total, 414.2 free, 2541.5 used, 2071.1 buff/cache +MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem + + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 5692 20 0 121504 8396 6644 R 94.4 0.2 155491:08 pan_task + 5695 20 0 121504 7840 6632 R 94.4 0.2 155491:01 pan_task + 5696 20 0 121504 8360 6816 R 94.4 0.2 155486:29 pan_task + 5699 20 0 121504 8132 6676 R 94.4 0.2 155236:17 pan_task + 5700 20 0 146304 18424 6780 R 88.9 0.4 155491:40 pan_task + +22360 nobody 20 0 459836 40592 10148 R 22.2 0.8 0:38.65 httpd + + 6374 17 -3 1078156 18272 9716 S 5.6 0.4 215:46.41 routed + +14227 20 0 18108 7184 2172 R 5.6 0.1 0:00.04 top + + 1 20 0 2532 696 656 S 0.0 0.0 3:48.14 init + 2 20 0 0 0 0 S 0.0 0.0 0:00.83 kthreadd +*/ +func formatResourceEvents(m *MetricSet, input string) []mb.Event { + timestamp := time.Now() + events := make([]mb.Event, 0) + + // We only need the top 5 lines + lines := strings.Split(input, "\n") + lines = lines[:5] + + systemInfo := parseSystemInfo(lines[0]) + taskInfo := parseTaskInfo(lines[1]) + cpuInfo := parseCPUInfo(lines[2]) + memoryInfo := parseMemoryInfo(lines[3]) + swapInfo := parseSwapInfo(lines[4]) + + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "uptime": mapstr.M{ + "days": systemInfo.Uptime.Days, + "hours": systemInfo.Uptime.Hours, + "minutes": systemInfo.Uptime.Minutes, + }, + "user_count": systemInfo.UserCount, + "load_average": mapstr.M{ + "1m": systemInfo.LoadAverage.OneMinute, + "5m": systemInfo.LoadAverage.FiveMinute, + "15m": systemInfo.LoadAverage.FifteenMinute, + }, + "tasks": mapstr.M{ + "total": taskInfo.Total, + "running": taskInfo.Running, + "sleeping": taskInfo.Sleeping, + "stopped": taskInfo.Stopped, + "zombie": taskInfo.Zombie, + }, + "cpu": mapstr.M{ + "user": cpuInfo.User, + "system": cpuInfo.System, + "nice": cpuInfo.Nice, + "idle": cpuInfo.Idle, + "wait": cpuInfo.Wait, + "hi": cpuInfo.Hi, + "system_int": cpuInfo.SystemInt, + "steal": cpuInfo.Steal, + }, + "memory": mapstr.M{ + "total": memoryInfo.Total, + "free": memoryInfo.Free, + "used": memoryInfo.Used, + "buffer_cache": memoryInfo.BufferCache, + }, + "swap": mapstr.M{ + "total": swapInfo.Total, + "free": swapInfo.Free, + "used": swapInfo.Used, + "available": swapInfo.Available, + }, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + }, + } + + events = append(events, event) + return events +} + +func parseLoadAverage(line string) SystemLoad { + reLoadAvg := regexp.MustCompile(`load average:\s+([\d.]+),\s+([\d.]+),\s+([\d.]+)`) + var load1, load5, load15 float64 + + if matches := reLoadAvg.FindStringSubmatch(line); matches != nil { + load1 = parseFloat("load1", matches[1]) + load5 = parseFloat("load5", matches[2]) + load15 = parseFloat("load15", matches[3]) + } + + return SystemLoad{load1, load5, load15} +} + +func parseUserCount(line string) int { + reUserCount := regexp.MustCompile(`(\d+)\s+user`) + var userCount int + if matches := reUserCount.FindStringSubmatch(line); matches != nil { + userCount = parseInt("userCount", matches[1]) + } + + return userCount +} + +func parseUptime(line string) Uptime { + // Uptime less than 1 hour + // top - 15:03:02 up 4 min, 1 user, load average: 1.77, 2.74, 1.34 + // Uptime less than 1 day + // top - 16:16:29 up 1:18, 1 user, load average: 0.00, 0.02, 0.01 + // Uptime 1 day or more + // top - 11:08:26 up 2 days, 23:02, 1 user, load average: 0.40, 0.23, 0.37 + + // Regular expressions to match different uptime formats + // up < 1 hour + reMin := regexp.MustCompile(`up\s+(\d+)\s+min`) + // up >= 1 hour < 1 day + reHourMin := regexp.MustCompile(`up\s+(\d+):(\d+)`) + // up >= 1 day + reDayHourMin := regexp.MustCompile(`up\s+(\d+)\s+days?,\s+(\d+):(\d+)`) + + var days, hours, minutes int + var matches []string + + if matches = reMin.FindStringSubmatch(line); matches != nil { + minutes = parseInt("minutes", matches[1]) + } else if matches = reHourMin.FindStringSubmatch(line); matches != nil { + hours = parseInt("hours", matches[1]) + minutes = parseInt("minutes", matches[2]) + } else if matches = reDayHourMin.FindStringSubmatch(line); matches != nil { + days = parseInt("days", matches[1]) + hours = parseInt("hours", matches[2]) + minutes = parseInt("minutes", matches[3]) + } + + if matches == nil { + logger.Errorf("Failed to parse uptime: %s", line) + return Uptime{} + } + + return Uptime{days, hours, minutes} +} + +func parseSystemInfo(line string) SystemInfo { + + uptime := parseUptime(line) + users := parseUserCount(line) + SystemLoad := parseLoadAverage(line) + + return SystemInfo{ + Uptime: uptime, + UserCount: users, + LoadAverage: SystemLoad, + } +} + +func parseTaskInfo(line string) TaskInfo { + //Tasks: 189 total, 7 running, 182 sleeping, 0 stopped, 0 zombie + + re := regexp.MustCompile(`Tasks:\s*(\d+)\s*total,\s*(\d+)\s*running,\s*(\d+)\s*sleeping,\s*(\d+)\s*stopped,\s*(\d+)\s*zombie`) + matches := re.FindStringSubmatch(line) + if matches == nil { + logger.Errorf("Failed to parse task info: %s", line) + return TaskInfo{} + } + + total := parseInt("total", matches[1]) + running := parseInt("running", matches[2]) + sleeping := parseInt("sleeping", matches[3]) + stopped := parseInt("stopped", matches[4]) + zombie := parseInt("zombie", matches[5]) + + return TaskInfo{ + Total: total, + Running: running, + Sleeping: sleeping, + Stopped: stopped, + Zombie: zombie, + } +} + +func parseCPUInfo(line string) CPUInfo { + //%Cpu(s): 73.0 us, 4.6 sy, 0.0 ni, 21.7 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st + re := regexp.MustCompile(`(\d+\.\d+) us, (\d+\.\d+) sy, (\d+\.\d+) ni, (\d+\.\d+) id, (\d+\.\d+) wa, (\d+\.\d+) hi, (\d+\.\d+) si, (\d+\.\d+) st`) + matches := re.FindStringSubmatch(line) + if matches == nil { + logger.Errorf("Failed to parse CPU info: %s", line) + return CPUInfo{} + } + + user := parseFloat("user", matches[1]) + system := parseFloat("system", matches[2]) + nice := parseFloat("nice", matches[3]) + idle := parseFloat("idle", matches[4]) + wait := parseFloat("wait", matches[5]) + hi := parseFloat("hi", matches[6]) + sysint := parseFloat("sysint", matches[7]) + steal := parseFloat("steal", matches[8]) + + return CPUInfo{ + User: user, + System: system, + Nice: nice, + Idle: idle, + Wait: wait, + Hi: hi, + SystemInt: sysint, + Steal: steal, + } +} + +func parseMemoryInfo(line string) MemoryInfo { + //MiB Mem : 5026.9 total, 414.2 free, 2541.5 used, 2071.1 buff/cache + re := regexp.MustCompile(`(\d+\.\d+)\s+total,\s+(\d+\.\d+)\s+free,\s+(\d+\.\d+)\s+used,\s+(\d+\.\d+)\s+buff/cache`) + matches := re.FindStringSubmatch(line) + + total := parseFloat("total", matches[1]) + free := parseFloat("free", matches[2]) + used := parseFloat("used", matches[3]) + bufferCache := parseFloat("bufferCache", matches[4]) + + return MemoryInfo{ + Total: total, + Free: free, + Used: used, + BufferCache: bufferCache, + } +} + +func parseSwapInfo(line string) SwapInfo { + //MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem + // Note: the punctuation after the "used" is a ".", not a "," + re := regexp.MustCompile(`(\d+\.\d+)\s+total,\s+(\d+\.\d+)\s+free,\s+(\d+\.\d+)\s+used[,\.].\s+(\d+\.\d+)\s+avail Mem`) + matches := re.FindStringSubmatch(line) + + total := parseFloat("total", matches[1]) + free := parseFloat("free", matches[2]) + used := parseFloat("used", matches[3]) + available := parseFloat("available", matches[4]) + + return SwapInfo{ + Total: total, + Free: free, + Used: used, + Available: available, + } +} + +func parseFloat(field string, value string) float64 { + var result float64 + result, err := strconv.ParseFloat(value, 64) + if err != nil { + logger.Errorf("parseFloat failed to parse field %s: %v", field, err) + return -1 + } + + return result +} + +func parseInt(field string, value string) int { + result, err := strconv.Atoi(value) + if err != nil { + logger.Errorf("parseInt failed to parse field %s: %v", field, err) + return -1 + } + return result +} diff --git a/x-pack/metricbeat/module/panos/system/system.go b/x-pack/metricbeat/module/panw/system/system.go similarity index 52% rename from x-pack/metricbeat/module/panos/system/system.go rename to x-pack/metricbeat/module/panw/system/system.go index a4d38ed0ed3..6458ac7edef 100644 --- a/x-pack/metricbeat/module/panos/system/system.go +++ b/x-pack/metricbeat/module/panw/system/system.go @@ -6,11 +6,11 @@ package system import ( "errors" - "strings" + "fmt" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/logp" ) @@ -25,9 +25,9 @@ const ( // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - config *panos.Config + config *panw.Config logger *logp.Logger - client panos.PanosClient + client panw.PanwClient } // init registers the MetricSet with the central registry as soon as the program @@ -35,15 +35,15 @@ type MetricSet struct { // the MetricSet for each host is defined in the module's configuration. After the // MetricSet has been created then Fetch will begin to be called periodically. func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) + mb.Registry.MustAddMetricSet(panw.ModuleName, metricsetName, New) } // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos system metricset is beta.") + cfgwarn.Beta("The panw system metricset is beta.") - config, err := panos.NewConfig(base) + config, err := panw.NewConfig(base) if err != nil { return nil, err } @@ -51,7 +51,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { logger := logp.NewLogger(base.FullyQualifiedName()) //client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - client, err := panos.GetPanosClient(config) + client, err := panw.GetPanwClient(config) if err != nil { return nil, err } @@ -70,83 +70,37 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { func (m *MetricSet) Fetch(report mb.ReporterV2) error { // accumulate errs and report them all at the end so that we don't // stop processing events if one of the fetches fails - var errs []string - - certificateEvents, err := getCertificateEvents(m) - if err != nil { - m.logger.Error("Error get certificate events: %s", err) - errs = append(errs, err.Error()) - } - - for _, event := range certificateEvents { - report.Event(event) - } - - resourceEvents, err := getResourceEvents(m) - if err != nil { - m.logger.Error("Error get resource events: %s", err) - errs = append(errs, err.Error()) - } - - for _, event := range resourceEvents { - report.Event(event) - } - - powerEvents, err := getPowerEvents(m) - if err != nil { - m.logger.Error("Error get power events: %s", err) - errs = append(errs, err.Error()) - - } - - for _, event := range powerEvents { - report.Event(event) - } - - fanEvents, err := getFanEvents(m) - if err != nil { - m.logger.Error("Error get fan events: %s", err) - errs = append(errs, err.Error()) - } - - for _, event := range fanEvents { - report.Event(event) - } - - thermalEvents, err := getThermalEvents(m) - if err != nil { - m.logger.Error("Error get thermal events: %s", err) - errs = append(errs, err.Error()) - } - - for _, event := range thermalEvents { - report.Event(event) - } - - licenesEvents, err := getLicenseEvents(m) - if err != nil { - m.logger.Error("Error get license events: %s", err) - errs = append(errs, err.Error()) - } - - for _, event := range licenesEvents { - report.Event(event) - } - - filesystemEvents, err := getFilesystemEvents(m) - if err != nil { - m.logger.Error("Error get filesystem events: %s", err) - errs = append(errs, err.Error()) - } - - for _, event := range filesystemEvents { - report.Event(event) + var errs []error + + eventFetchers := []struct { + name string + fn func(*MetricSet) ([]mb.Event, error) + }{ + {"certificates", getCertificateEvents}, + {"resources", getResourceEvents}, + {"power", getPowerEvents}, + {"fans", getFanEvents}, + {"thermal", getThermalEvents}, + {"licenses", getLicenseEvents}, + {"filesystem", getFilesystemEvents}, + } + + for _, fetcher := range eventFetchers { + events, err := fetcher.fn(m) + if err != nil { + m.logger.Errorf("Error getting %s events: %s", fetcher.name, err) + errs = append(errs, err) + } else { + for _, event := range events { + report.Event(event) + } + } } if len(errs) > 0 { - return errors.New(strings.Join(errs, "; ")) - } else { - return nil + return fmt.Errorf("error while fetching vpn metrics: %w", errors.Join(errs...)) } + return nil + } diff --git a/x-pack/metricbeat/module/panos/system/system_types.go b/x-pack/metricbeat/module/panw/system/system_types.go similarity index 98% rename from x-pack/metricbeat/module/panos/system/system_types.go rename to x-pack/metricbeat/module/panw/system/system_types.go index d130b9a2e75..4f821477ecb 100644 --- a/x-pack/metricbeat/module/panos/system/system_types.go +++ b/x-pack/metricbeat/module/panw/system/system_types.go @@ -15,9 +15,9 @@ type ResourceResponse struct { } type SystemLoad struct { - one_minute float64 - five_minute float64 - fifteen_minute float64 + OneMinute float64 + FiveMinute float64 + FifteenMinute float64 } type Uptime struct { diff --git a/x-pack/metricbeat/module/panos/system/thermal.go b/x-pack/metricbeat/module/panw/system/thermal.go similarity index 63% rename from x-pack/metricbeat/module/panos/system/thermal.go rename to x-pack/metricbeat/module/panw/system/thermal.go index 2ab4f6e805a..70c597ea776 100644 --- a/x-pack/metricbeat/module/panos/system/thermal.go +++ b/x-pack/metricbeat/module/panw/system/thermal.go @@ -12,12 +12,12 @@ import ( "github.com/elastic/elastic-agent-libs/mapstr" ) +const thermalQuery = "" + func getThermalEvents(m *MetricSet) ([]mb.Event, error) { var response ThermalResponse - query := "" - - output, err := m.client.Op(query, vsys, nil, nil) + output, err := m.client.Op(thermalQuery, vsys, nil, nil) if err != nil { m.logger.Error("Error: %s", err) return nil, err @@ -36,28 +36,32 @@ func getThermalEvents(m *MetricSet) ([]mb.Event, error) { } func formatThermalEvents(m *MetricSet, response *ThermalResponse) []mb.Event { - log := m.Logger() + if response == nil || len(response.Result.Thermal.Slots) == 0 { + return nil + } + events := make([]mb.Event, 0, len(response.Result.Thermal.Slots)) - currentTime := time.Now() + timestamp := time.Now() var event mb.Event + for _, slot := range response.Result.Thermal.Slots { for _, entry := range slot.Entries { - log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) - event = mb.Event{MetricSetFields: mapstr.M{ - - "thermal.slot_number": entry.Slot, - "thermal.description": entry.Description, - "thermal.alarm": entry.Alarm, - "thermal.degress_celsius": entry.DegreesCelsius, - "thermal.minimum_temp": entry.MinimumTemp, - "thermal.maximum_temp": entry.MaximumTemp, - }, + m.logger.Debugf("Processing slot %d entry %+v", entry.Slot, entry) + event = mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "thermal.slot_number": entry.Slot, + "thermal.description": entry.Description, + "thermal.alarm": entry.Alarm, + "thermal.degress_celsius": entry.DegreesCelsius, + "thermal.minimum_temp": entry.MinimumTemp, + "thermal.maximum_temp": entry.MaximumTemp, + }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, "host.ip": m.config.HostIp, "observer.vendor": "Palo Alto", "observer.type": "firewall", - "@Timestamp": currentTime, }} } diff --git a/x-pack/metricbeat/module/panw/util.go b/x-pack/metricbeat/module/panw/util.go new file mode 100644 index 00000000000..245a35629c3 --- /dev/null +++ b/x-pack/metricbeat/module/panw/util.go @@ -0,0 +1,18 @@ +package panw + +import ( + "fmt" + "strings" +) + +func StringToBool(s string) (bool, error) { + s = strings.ToLower(s) + switch s { + case "yes": + return true, nil + case "no": + return false, nil + default: + return false, fmt.Errorf("invalid value: %s", s) + } +} diff --git a/x-pack/metricbeat/module/panos/vpn/_meta/data.json b/x-pack/metricbeat/module/panw/vpn/_meta/data.json similarity index 100% rename from x-pack/metricbeat/module/panos/vpn/_meta/data.json rename to x-pack/metricbeat/module/panw/vpn/_meta/data.json diff --git a/x-pack/metricbeat/module/panos/vpn/_meta/docs.asciidoc b/x-pack/metricbeat/module/panw/vpn/_meta/docs.asciidoc similarity index 100% rename from x-pack/metricbeat/module/panos/vpn/_meta/docs.asciidoc rename to x-pack/metricbeat/module/panw/vpn/_meta/docs.asciidoc diff --git a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml new file mode 100644 index 00000000000..3dd1ed5e028 --- /dev/null +++ b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml @@ -0,0 +1,194 @@ +- name: vpn + type: group + release: beta + description: > + vpn + fields: + - name: globalprotect.session.domain + type: keyword + description: > + Domain of the GlobalProtect session + - name: globalprotect.session.is_local + type: boolean + description: > + Indicates if the session is local + - name: globalprotect.session.username + type: keyword + description: > + Username of the session + - name: globalprotect.session.primary_username + type: keyword + description: > + Primary username of the session + - name: globalprotect.session.region_for_config + type: keyword + description: > + Region for configuration + - name: globalprotect.session.source_region + type: keyword + description: > + Source region of the session + - name: globalprotect.session.computer + type: keyword + description: > + Computer name in the session + - name: globalprotect.session.client + type: keyword + description: > + Client information of the session + - name: globalprotect.session.vpn_type + type: keyword + description: > + Type of VPN used in the session + - name: globalprotect.session.host_id + type: keyword + description: > + Host ID of the session + - name: globalprotect.session.app_version + type: keyword + description: > + Application version used in the session + - name: globalprotect.session.virtual_ip + type: ip + description: > + Virtual IP address of the session + - name: globalprotect.session.virtual_ipv6 + type: ip + description: > + Virtual IPv6 address of the session + - name: globalprotect.session.public_ip + type: ip + description: > + Public IP address of the session + - name: globalprotect.session.public_ipv6 + type: ip + description: > + Public IPv6 address of the session + - name: globalprotect.session.tunnel_type + type: keyword + description: > + Type of tunnel used in the session + - name: globalprotect.session.public_connection_ipv6 + type: ip + description: > + Public connection IPv6 address of the session + - name: globalprotect.session.client_ip + type: ip + description: > + Client IP address of the session + - name: globalprotect.session.login_time + type: date + description: > + Login time of the session + - name: globalprotect.session.login_time_utc + type: date + description: > + Login time in UTC of the session + - name: globalprotect.session.lifetime + type: long + description: > + Lifetime of the session + - name: globalprotect.session.request_login + type: keyword + description: > + Request login information of the session + - name: globalprotect.session.request_get_config + type: keyword + description: > + Request get configuration information of the session + - name: globalprotect.session.request_sslvpn_connect + type: keyword + description: > + Request SSL VPN connect information of the session + - name: globalprotect.gateway.name + type: keyword + description: > + Name of the GlobalProtect gateway + - name: globalprotect.gateway.current_users + type: long + description: > + Current number of users connected to the GlobalProtect gateway + - name: globalprotect.gateway.previous_users + type: long + description: > + Previous number of users connected to the GlobalProtect gateway + - name: globalprotect.total_current_users + type: long + description: > + Total current number of users connected to GlobalProtect + - name: globalprotect.total_previous_users + type: long + description: > + Total previous number of users connected to GlobalProtect + - name: ipsec_tunnel.id + type: keyword + description: > + ID of the IPsec tunnel + - name: ipsec_tunnel.name + type: keyword + description: > + Name of the IPsec tunnel + - name: ipsec_tunnel.gw + type: keyword + description: > + Gateway of the IPsec tunnel + - name: ipsec_tunnel.TSi_ip + type: ip + description: > + TSi IP address of the IPsec tunnel + - name: ipsec_tunnel.TSi_prefix + type: keyword + description: > + TSi prefix of the IPsec tunnel + - name: ipsec_tunnel.TSi_proto + type: keyword + description: > + TSi protocol of the IPsec tunnel + - name: ipsec_tunnel.TSi_port + type: long + description: > + TSi port of the IPsec tunnel + - name: ipsec_tunnel.TSr_ip + type: ip + description: > + TSr IP address of the IPsec tunnel + - name: ipsec_tunnel.TSr_prefix + type: keyword + description: > + TSr prefix of the IPsec tunnel + - name: ipsec_tunnel.TSr_proto + type: keyword + description: > + TSr protocol of the IPsec tunnel + - name: ipsec_tunnel.TSr_port + type: long + description: > + TSr port of the IPsec tunnel + - name: ipsec_tunnel.proto + type: keyword + description: > + Protocol of the IPsec tunnel + - name: ipsec_tunnel.mode + type: keyword + description: > + Mode of the IPsec tunnel + - name: ipsec_tunnel.dh + type: keyword + description: > + Diffie-Hellman group of the IPsec tunnel + - name: ipsec_tunnel.enc + type: keyword + description: > + Encryption algorithm of the IPsec tunnel + - name: ipsec_tunnel.hash + type: keyword + description: > + Hash algorithm of the IPsec tunnel + - name: ipsec_tunnel.life + type: long + description: > + Lifetime of the IPsec tunnel + - name: ipsec_tunnel.kb + type: long + description: > + Key bytes of the IPsec tunnel \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/vpn/gp_sessions.go b/x-pack/metricbeat/module/panw/vpn/gp_sessions.go new file mode 100644 index 00000000000..e4b54bab028 --- /dev/null +++ b/x-pack/metricbeat/module/panw/vpn/gp_sessions.go @@ -0,0 +1,87 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package vpn + +import ( + "encoding/xml" + "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +const gpSessionsQuery = "" + +func getGlobalProtectSessionEvents(m *MetricSet) ([]mb.Event, error) { + var response GPSessionsResponse + + output, err := m.client.Op(gpSessionsQuery, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, fmt.Errorf("error querying GlobalProtect sessions: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, fmt.Errorf("error unmarshaling GlobalProtect sessions response: %w", err) + } + + events := formatGPSessionEvents(m, response.Result.Sessions) + + return events, nil + +} + +func formatGPSessionEvents(m *MetricSet, sessions []GPSession) []mb.Event { + if sessions == nil { + return nil + } + + events := make([]mb.Event, 0, len(sessions)) + timestamp := time.Now() + + for _, session := range sessions { + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "globalprotect.session.domain": session.Domain, + "globalprotect.session.is_local": session.IsLocal, + "globalprotect.session.username": session.Username, + "globalprotect.session.rimary_username": session.PrimaryUsername, + "globalprotect.session.region_for_config": session.RegionForConfig, + "globalprotect.session.source_region": session.SourceRegion, + "globalprotect.session.computer": session.Computer, + "globalprotect.session.client": session.Client, + "globalprotect.session.vpn_type": session.VPNType, + "globalprotect.session.host_id": session.HostID, + "globalprotect.session.app_version": session.AppVersion, + "globalprotect.session.virtual_ip": session.VirtualIP, + "globalprotect.session.virtual_ipv6": session.VirtualIPv6, + "globalprotect.session.public_ip": session.PublicIP, + "globalprotect.session.public_ipv6": session.PublicIPv6, + "globalprotect.session.tunnel_type": session.TunnelType, + "globalprotect.session.public_connection_ipv6": session.PublicConnectionIPv6, + "globalprotect.session.lient_ip": session.ClientIP, + "globalprotect.session.login_time": session.LoginTime, + "globalprotect.session.login_time_utc": session.LoginTimeUTC, + "globalprotect.session.lifetime": session.Lifetime, + "globalprotect.session.request_login": session.RequestLogin, + "globalprotect.session.request_get_config": session.RequestGetConfig, + "globalprotect.session.request_sslvpn_connect": session.RequestSSLVPNConnect, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + }} + + events = append(events, event) + } + + return events +} diff --git a/x-pack/metricbeat/module/panos/vpn/gp_stats.go b/x-pack/metricbeat/module/panw/vpn/gp_stats.go similarity index 60% rename from x-pack/metricbeat/module/panos/vpn/gp_stats.go rename to x-pack/metricbeat/module/panw/vpn/gp_stats.go index f7177fe3009..8500bafeb1c 100644 --- a/x-pack/metricbeat/module/panos/vpn/gp_stats.go +++ b/x-pack/metricbeat/module/panw/vpn/gp_stats.go @@ -6,26 +6,29 @@ package vpn import ( "encoding/xml" + "fmt" "time" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/elastic-agent-libs/mapstr" ) +const gpStatsQuery = "" + func getGlobalProtectStatsEvents(m *MetricSet) ([]mb.Event, error) { - query := "" + var response GPStatsResponse - output, err := m.client.Op(query, vsys, nil, nil) + output, err := m.client.Op(gpStatsQuery, vsys, nil, nil) if err != nil { m.logger.Error("Error: %s", err) - return nil, err + return nil, fmt.Errorf("error querying GlobalProtect statistics: %w", err) } err = xml.Unmarshal(output, &response) if err != nil { m.logger.Error("Error: %s", err) - return nil, err + return nil, fmt.Errorf("error unmarshaling GlobalProtect statistics response: %w", err) } events := formatGPStatsEvents(m, response) @@ -35,26 +38,32 @@ func getGlobalProtectStatsEvents(m *MetricSet) ([]mb.Event, error) { } func formatGPStatsEvents(m *MetricSet, response GPStatsResponse) []mb.Event { + + if len(response.Result.Gateways) == 0 { + return nil + } + events := make([]mb.Event, 0, len(response.Result.Gateways)) + timestamp := time.Now() - currentTime := time.Now() totalCurrent := response.Result.TotalCurrentUsers totalPrevious := response.Result.TotalPreviousUsers for _, gateway := range response.Result.Gateways { - event := mb.Event{MetricSetFields: mapstr.M{ - "globalprotect.gateway.name": gateway.Name, - "globalprotect.gateway.current_users": gateway.CurrentUsers, - "globalprotect.gateway.previous_users": gateway.PreviousUsers, - "globalprotect.total_current_users": totalCurrent, - "globalprotect.total_previous_users": totalPrevious, - }, + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "globalprotect.gateway.name": gateway.Name, + "globalprotect.gateway.current_users": gateway.CurrentUsers, + "globalprotect.gateway.previous_users": gateway.PreviousUsers, + "globalprotect.total_current_users": totalCurrent, + "globalprotect.total_previous_users": totalPrevious, + }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, "host.ip": m.config.HostIp, "observer.vendor": "Palo Alto", "observer.type": "firewall", - "@Timestamp": currentTime, }} events = append(events, event) diff --git a/x-pack/metricbeat/module/panw/vpn/tunnels.go b/x-pack/metricbeat/module/panw/vpn/tunnels.go new file mode 100644 index 00000000000..241c075e85f --- /dev/null +++ b/x-pack/metricbeat/module/panw/vpn/tunnels.go @@ -0,0 +1,83 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package vpn + +import ( + "encoding/xml" + "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" +) + +const IPSecTunnelsQuery = "" + +func getIPSecTunnelEvents(m *MetricSet) ([]mb.Event, error) { + + var response TunnelsResponse + + output, err := m.client.Op(IPSecTunnelsQuery, vsys, nil, nil) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, fmt.Errorf("error querying IPSec tunnels: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { + m.logger.Error("Error: %s", err) + return nil, fmt.Errorf("error unmarshaling IPSec tunnels response: %w", err) + } + + events := formatIPSecTunnelEvents(m, response.Result.Entries) + + return events, nil + +} + +func formatIPSecTunnelEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { + if entries == nil { + return nil + } + + events := make([]mb.Event, 0, len(entries)) + timestamp := time.Now() + + for _, entry := range entries { + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "ipsec_tunnel.id": entry.ID, + "ipsec_tunnel.name": entry.Name, + "ipsec_tunnel.gw": entry.GW, + "ipsec_tunnel.TSi_ip": entry.TSiIP, + "ipsec_tunnel.TSi_prefix": entry.TSiPrefix, + "ipsec_tunnel.TSi_proto": entry.TSiProto, + "ipsec_tunnel.TSi_port": entry.TSiPort, + "ipsec_tunnel.TSr_ip": entry.TSrIP, + "ipsec_tunnel.TSr_prefix": entry.TSrPrefix, + "ipsec_tunnel.TSr_proto": entry.TSrProto, + "ipsec_tunnel.TSr_port": entry.TSrPort, + "ipsec_tunnel.proto": entry.Proto, + "ipsec_tunnel.mode": entry.Mode, + "ipsec_tunnel.dh": entry.DH, + "ipsec_tunnel.enc": entry.Enc, + "ipsec_tunnel.hash": entry.Hash, + "ipsec_tunnel.life": entry.Life, + "ipsec_tunnel.kb": entry.KB, + }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + }} + + events = append(events, event) + } + + return events + +} diff --git a/x-pack/metricbeat/module/panos/vpn/vpn.go b/x-pack/metricbeat/module/panw/vpn/vpn.go similarity index 65% rename from x-pack/metricbeat/module/panos/vpn/vpn.go rename to x-pack/metricbeat/module/panw/vpn/vpn.go index e3f428bbf58..d7d838bcc01 100644 --- a/x-pack/metricbeat/module/panos/vpn/vpn.go +++ b/x-pack/metricbeat/module/panw/vpn/vpn.go @@ -6,11 +6,11 @@ package vpn import ( "errors" - "strings" + "fmt" "github.com/elastic/beats/v7/libbeat/common/cfgwarn" "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/beats/v7/x-pack/metricbeat/module/panos" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/logp" ) @@ -25,9 +25,9 @@ const ( // interface methods except for Fetch. type MetricSet struct { mb.BaseMetricSet - config *panos.Config + config *panw.Config logger *logp.Logger - client panos.PanosClient + client panw.PanwClient } // init registers the MetricSet with the central registry as soon as the program @@ -35,15 +35,15 @@ type MetricSet struct { // the MetricSet for each host is defined in the module's configuration. After the // MetricSet has been created then Fetch will begin to be called periodically. func init() { - mb.Registry.MustAddMetricSet(panos.ModuleName, metricsetName, New) + mb.Registry.MustAddMetricSet(panw.ModuleName, metricsetName, New) } // New creates a new instance of the MetricSet. New is responsible for unpacking // any MetricSet specific configuration options if there are any. func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - cfgwarn.Beta("The panos vpn metricset is beta.") + cfgwarn.Beta("The panw vpn metricset is beta.") - config, err := panos.NewConfig(base) + config, err := panw.NewConfig(base) if err != nil { return nil, err } @@ -51,7 +51,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { logger := logp.NewLogger(base.FullyQualifiedName()) //client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - client, err := panos.GetPanosClient(config) + client, err := panw.GetPanwClient(config) if err != nil { return nil, err } @@ -70,42 +70,33 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { func (m *MetricSet) Fetch(report mb.ReporterV2) error { // accumulate errs and report them all at the end so that we don't // stop processing events if one of the fetches fails - var errs []string - - gpSessionEvents, err := getGlobalProtectSessionEvents(m) - if err != nil { - m.logger.Error("Error get GlobalProtect session events: %s", err) - errs = append(errs, err.Error()) - } - - for _, event := range gpSessionEvents { - report.Event(event) - } - - gpStatsEvents, err := getGlobalProtectStatsEvents(m) - if err != nil { - m.logger.Error("Error get GlobalProtect stats events: %s", err) - errs = append(errs, err.Error()) + var errs []error + + eventFetchers := []struct { + name string + fn func(*MetricSet) ([]mb.Event, error) + }{ + {"globalprotect session", getGlobalProtectSessionEvents}, + {"globalprotect stats", getGlobalProtectStatsEvents}, + {"ipsec tunnel", getIPSecTunnelEvents}, } - for _, event := range gpStatsEvents { - report.Event(event) - } - - ipsecTunnelsEvents, err := getIPSecTunnelEvents(m) - if err != nil { - m.logger.Error("Error get IPSec Tunnel events: %s", err) - errs = append(errs, err.Error()) - } - - for _, event := range ipsecTunnelsEvents { - report.Event(event) + for _, fetcher := range eventFetchers { + events, err := fetcher.fn(m) + if err != nil { + m.logger.Errorf("Error getting %s events: %s", fetcher.name, err) + errs = append(errs, err) + } else { + for _, event := range events { + report.Event(event) + } + } } if len(errs) > 0 { - return errors.New(strings.Join(errs, "; ")) - } else { - return nil + return fmt.Errorf("error while fetching vpn metrics: %w", errors.Join(errs...)) } + return nil + } diff --git a/x-pack/metricbeat/module/panos/vpn/vpn_types.go b/x-pack/metricbeat/module/panw/vpn/vpn_types.go similarity index 100% rename from x-pack/metricbeat/module/panos/vpn/vpn_types.go rename to x-pack/metricbeat/module/panw/vpn/vpn_types.go diff --git a/x-pack/metricbeat/modules.d/panos.yml.disabled b/x-pack/metricbeat/modules.d/panw.yml.disabled similarity index 100% rename from x-pack/metricbeat/modules.d/panos.yml.disabled rename to x-pack/metricbeat/modules.d/panw.yml.disabled diff --git a/x-pack/metricbeat/patch1.diff b/x-pack/metricbeat/patch1.diff new file mode 100644 index 00000000000..823a6c5bc95 --- /dev/null +++ b/x-pack/metricbeat/patch1.diff @@ -0,0 +1,717 @@ +diff --git a/go.mod b/go.mod +index a47bf7ec15..193648d401 100644 +--- a/go.mod ++++ b/go.mod +@@ -181,6 +181,7 @@ require ( + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.0 + github.com/Azure/azure-storage-blob-go v0.15.0 + github.com/Azure/go-autorest/autorest/adal v0.9.24 ++ github.com/PaloAltoNetworks/pango v0.10.2 + github.com/apache/arrow/go/v14 v14.0.2 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.13 +diff --git a/go.sum b/go.sum +index ec32ee823d..d9ce04d812 100644 +--- a/go.sum ++++ b/go.sum +@@ -215,6 +215,8 @@ github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbV + github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= + github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= + github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= ++github.com/PaloAltoNetworks/pango v0.10.2 h1:Tjn6vIzzAq6Dd7N0mDuiP8w8pz8k5W9zz/TTSUQCsQY= ++github.com/PaloAltoNetworks/pango v0.10.2/go.mod h1:GztcRnVLur7G+VFG7Z5ZKNFgScLtsycwPMp1qVebE5g= + github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= + github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= + github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +diff --git a/x-pack/metricbeat/module/panos/system/certificates.go b/x-pack/metricbeat/module/panos/system/certificates.go +index ca81bfcc91..1ae5c5cf39 100644 +--- a/x-pack/metricbeat/module/panos/system/certificates.go ++++ b/x-pack/metricbeat/module/panos/system/certificates.go +@@ -6,6 +6,8 @@ package system + + import ( + "encoding/xml" ++ "errors" ++ "fmt" + "regexp" + "strings" + "time" +@@ -20,29 +22,39 @@ func getCertificateEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to execute query: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + +- events := formatCertificateEvents(m, response.Result) ++ if response.Result == "" { ++ return nil, fmt.Errorf("empty result from XML response") ++ } ++ ++ events, err := formatCertificateEvents(m, response.Result) ++ if err != nil { ++ return nil, fmt.Errorf("failed to format certificate events: %w", err) ++ } + + return events, nil + } + +-func formatCertificateEvents(m *MetricSet, input string) []mb.Event { +- currentTime := time.Now() ++func formatCertificateEvents(m *MetricSet, input string) ([]mb.Event, error) { ++ timestamp := time.Now() ++ ++ certificates, err := parseCertificates(input) ++ if err != nil { ++ return nil, err ++ } + +- certificates := parseCertificates(input) + events := make([]mb.Event, 0, len(certificates)) + + for _, certificate := range certificates { + event := mb.Event{ ++ Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "certificate.name": certificate.CertName, + "certificate.issuer": certificate.Issuer, +@@ -61,59 +73,78 @@ func formatCertificateEvents(m *MetricSet, input string) []mb.Event { + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } + + events = append(events, event) + } + +- return events ++ return events, nil + } + +-func parseCertificates(input string) []Certificate { ++const ( ++ issuerPrefix = "issuer: " ++ issuerSubjectHashPrefix = "issuer-subjecthash: " ++ issuerKeyHashPrefix = "issuer-keyhash: " ++ dbTypePrefix = "db-type: " ++ dbExpDatePrefix = "db-exp-date: " ++ dbRevDatePrefix = "db-rev-date: " ++ dbSerialNoPrefix = "db-serialno: " ++ dbFilePrefix = "db-file: " ++ dbNamePrefix = "db-name: " ++ dbStatusPrefix = "db-status: " ++) ++ ++func parseCertificates(input string) ([]Certificate, error) { + lines := strings.Split(input, "\n") + pattern := `^[0-9A-Fa-f]{1,40}:[0-9A-Fa-f]{40}([0-9A-Fa-f]{24})?$` + regex := regexp.MustCompile(pattern) +- var certificates []Certificate ++ ++ certificates := make([]Certificate, 0) + var currentSN Certificate + + for _, line := range lines { + line = strings.TrimSpace(line) +- if regex.MatchString(line) { ++ switch { ++ case regex.MatchString(line): + if currentSN.CertName != "" { + certificates = append(certificates, currentSN) + currentSN = Certificate{} + } + currentSN.CertName = line +- } else if strings.HasPrefix(line, "issuer:") { +- currentSN.Issuer = strings.TrimPrefix(line, "issuer: ") +- } else if strings.HasPrefix(line, "issuer-subjecthash:") { +- currentSN.IssuerSubjectHash = strings.TrimPrefix(line, "issuer-subjecthash: ") +- } else if strings.HasPrefix(line, "issuer-keyhash:") { +- currentSN.IssuerKeyHash = strings.TrimPrefix(line, "issuer-keyhash: ") +- if strings.HasPrefix(currentSN.IssuerKeyHash, "issuer-keyhash:") { ++ case strings.HasPrefix(line, issuerPrefix): ++ currentSN.Issuer = strings.TrimPrefix(line, issuerPrefix) ++ case strings.HasPrefix(line, issuerSubjectHashPrefix): ++ currentSN.IssuerSubjectHash = strings.TrimPrefix(line, issuerSubjectHashPrefix) ++ case strings.HasPrefix(line, issuerKeyHashPrefix): ++ currentSN.IssuerKeyHash = strings.TrimPrefix(line, issuerKeyHashPrefix) ++ if strings.HasPrefix(currentSN.IssuerKeyHash, issuerKeyHashPrefix) { + currentSN.IssuerKeyHash = "" + } +- } else if strings.HasPrefix(line, "db-type:") { +- currentSN.DBType = strings.TrimPrefix(line, "db-type: ") +- } else if strings.HasPrefix(line, "db-exp-date:") { +- currentSN.DBExpDate = strings.TrimPrefix(line, "db-exp-date: ") +- } else if strings.HasPrefix(line, "db-rev-date:") { +- currentSN.DBRevDate = strings.TrimPrefix(line, "db-rev-date: ") +- } else if strings.HasPrefix(line, "db-serialno:") { +- currentSN.DBSerialNo = strings.TrimPrefix(line, "db-serialno: ") +- } else if strings.HasPrefix(line, "db-file:") { +- currentSN.DBFile = strings.TrimPrefix(line, "db-file: ") +- } else if strings.HasPrefix(line, "db-name:") { +- currentSN.DBName = strings.TrimPrefix(line, "db-name: ") +- } else if strings.HasPrefix(line, "db-status:") { +- currentSN.DBStatus = strings.TrimPrefix(line, "db-status: ") ++ case strings.HasPrefix(line, dbTypePrefix): ++ currentSN.DBType = strings.TrimPrefix(line, dbTypePrefix) ++ case strings.HasPrefix(line, dbExpDatePrefix): ++ currentSN.DBExpDate = strings.TrimPrefix(line, dbExpDatePrefix) ++ case strings.HasPrefix(line, dbRevDatePrefix): ++ currentSN.DBRevDate = strings.TrimPrefix(line, dbRevDatePrefix) ++ case strings.HasPrefix(line, dbSerialNoPrefix): ++ currentSN.DBSerialNo = strings.TrimPrefix(line, dbSerialNoPrefix) ++ case strings.HasPrefix(line, dbFilePrefix): ++ currentSN.DBFile = strings.TrimPrefix(line, dbFilePrefix) ++ case strings.HasPrefix(line, dbNamePrefix): ++ currentSN.DBName = strings.TrimPrefix(line, dbNamePrefix) ++ case strings.HasPrefix(line, dbStatusPrefix): ++ currentSN.DBStatus = strings.TrimPrefix(line, dbStatusPrefix) + } + } + +- if currentSN.Issuer != "" { ++ if currentSN.CertName != "" { + certificates = append(certificates, currentSN) + } + +- return certificates ++ if len(certificates) == 0 { ++ return nil, errors.New("no valid certificates found") ++ } ++ ++ return certificates, nil + } +diff --git a/x-pack/metricbeat/module/panos/system/fans.go b/x-pack/metricbeat/module/panos/system/fans.go +index 3e04299b2f..b725d83966 100644 +--- a/x-pack/metricbeat/module/panos/system/fans.go ++++ b/x-pack/metricbeat/module/panos/system/fans.go +@@ -6,6 +6,7 @@ package system + + import ( + "encoding/xml" ++ "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" +@@ -18,46 +19,46 @@ func getFanEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error querying fan data: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error unmarshaling fan data: %w", err) + } + +- events := formatFanEvents(m, &response) +- +- return events, nil ++ return formatFanEvents(m, &response), nil + } + + func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { +- log := m.Logger() +- events := make([]mb.Event, 0, len(response.Result.Fan.Slots)) +- currentTime := time.Now() +- var event mb.Event ++ if response == nil || len(response.Result.Fan.Slots) == 0 { ++ return nil ++ } ++ ++ events := make([]mb.Event, 0) ++ timestamp := time.Now() ++ + for _, slot := range response.Result.Fan.Slots { + for _, entry := range slot.Entries { +- log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) +- event = mb.Event{MetricSetFields: mapstr.M{ +- "fan.slot_number": entry.Slot, +- "fan.description": entry.Description, +- "fan.alarm": entry.Alarm, +- "fan.rpm": entry.RPMs, +- "fan.min_rpm": entry.Min, +- }, ++ m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "fan.slot_number": entry.Slot, ++ "fan.description": entry.Description, ++ "fan.alarm": entry.Alarm, ++ "fan.rpm": entry.RPMs, ++ "fan.min_rpm": entry.Min, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } ++ events = append(events, event) + } +- +- events = append(events, event) + } + + return events +diff --git a/x-pack/metricbeat/module/panos/system/filesystem.go b/x-pack/metricbeat/module/panos/system/filesystem.go +index 4adc63c3dc..e75eac63ef 100644 +--- a/x-pack/metricbeat/module/panos/system/filesystem.go ++++ b/x-pack/metricbeat/module/panos/system/filesystem.go +@@ -6,6 +6,7 @@ package system + + import ( + "encoding/xml" ++ "fmt" + "strings" + "time" + +@@ -20,39 +21,38 @@ func getFilesystemEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error querying filesystem info: %w", err) ++ } ++ ++ if len(output) == 0 { ++ return nil, fmt.Errorf("received empty output from filesystem query") + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error unmarshaling filesystem response: %w", err) + } + + filesystems := getFilesystems(response.Result.Data) +- events := formatFilesytemEvents(m, filesystems) ++ events := formatFilesystemEvents(m, filesystems) + + return events, nil + } + +-/* +-Result from the XML API call is basically linux df -h output: +-Filesystem Size Used Avail Use% Mounted on +-/dev/root 9.5G 4.0G 5.1G 44% / +-none 2.5G 64K 2.5G 1% /dev +-/dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg +-/dev/sda6 7.6G 3.1G 4.2G 43% /opt/panrepo +-tmpfs 2.5G 399M 2.1G 16% /dev/shm +-cgroup_root 2.5G 0 2.5G 0% /cgroup +-/dev/sda8 173G 63G 102G 39% /opt/panlogs +-tmpfs 12M 44K 12M 1% /opt/pancfg/mgmt/ssl/private +-*/ + func getFilesystems(input string) []Filesystem { + lines := strings.Split(input, "\n") + filesystems := make([]Filesystem, 0) + +- // Skip the first line which is the header ++ // Skip the first line which is the header: ++ // ++ // Example: ++ // Result from the XML API call is basically a command in Linux distribution i.e., "df -h"'s output: ++ // ++ // Filesystem Size Used Avail Use% Mounted on ++ // /dev/root 9.5G 4.0G 5.1G 44% / ++ // none 2.5G 64K 2.5G 1% /dev ++ // /dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg ++ // + for _, line := range lines[1:] { + fields := strings.Fields(line) + if len(fields) == 6 { +@@ -70,31 +70,35 @@ func getFilesystems(input string) []Filesystem { + return filesystems + } + +-func formatFilesytemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { +- events := make([]mb.Event, 0, len(filesystems)) ++func formatFilesystemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { ++ if len(filesystems) == 0 { ++ return nil ++ } + +- currentTime := time.Now() ++ events := make([]mb.Event, 0, len(filesystems)) ++ timestamp := time.Now() + + for _, filesystem := range filesystems { +- event := mb.Event{MetricSetFields: mapstr.M{ +- "filesystem.name": filesystem.Name, +- "filesystem.size": filesystem.Size, +- "filesystem.used": filesystem.Used, +- "filesystem.available": filesystem.Avail, +- "filesystem.use_percent": filesystem.UsePerc, +- "filesystem.mounted": filesystem.Mounted, +- }, ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "filesystem.name": filesystem.Name, ++ "filesystem.size": filesystem.Size, ++ "filesystem.used": filesystem.Used, ++ "filesystem.available": filesystem.Avail, ++ "filesystem.use_percent": filesystem.UsePerc, ++ "filesystem.mounted": filesystem.Mounted, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } + + events = append(events, event) + } + + return events +- + } +diff --git a/x-pack/metricbeat/module/panos/system/license.go b/x-pack/metricbeat/module/panos/system/license.go +index d12f03b8c1..88ae64050d 100644 +--- a/x-pack/metricbeat/module/panos/system/license.go ++++ b/x-pack/metricbeat/module/panos/system/license.go +@@ -6,6 +6,7 @@ package system + + import ( + "encoding/xml" ++ "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" +@@ -18,48 +19,52 @@ func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to execute query: %w", err) ++ } ++ ++ if len(output) == 0 { ++ return nil, fmt.Errorf("empty response from PanOS") + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + +- events := formatLicenseEvents(m, response.Result.Licenses) +- +- return events, nil ++ if len(response.Result.Licenses) == 0 { ++ m.logger.Warn("No licenses found in the response") ++ return nil, nil ++ } + ++ return formatLicenseEvents(m, response.Result.Licenses), nil + } + + func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { + events := make([]mb.Event, 0, len(licenses)) +- +- currentTime := time.Now() ++ timestamp := time.Now() + + for _, license := range licenses { +- event := mb.Event{MetricSetFields: mapstr.M{ +- "license.feature": license.Feature, +- "license.escription": license.Description, +- "license.serial": license.Serial, +- "license.issued": license.Issued, +- "license.expires": license.Expires, +- "license.expired": license.Expired, +- "license.auth_code": license.AuthCode, +- }, ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "license.feature": license.Feature, ++ "license.description": license.Description, // Fixed typo ++ "license.serial": license.Serial, ++ "license.issued": license.Issued, ++ "license.expires": license.Expires, ++ "license.expired": license.Expired, ++ "license.auth_code": license.AuthCode, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } + + events = append(events, event) + } + + return events +- + } +diff --git a/x-pack/metricbeat/module/panos/system/power.go b/x-pack/metricbeat/module/panos/system/power.go +index d5a4aa8487..a7540ad618 100644 +--- a/x-pack/metricbeat/module/panos/system/power.go ++++ b/x-pack/metricbeat/module/panos/system/power.go +@@ -6,27 +6,31 @@ package system + + import ( + "encoding/xml" ++ "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" + ) + ++// getPowerEvents retrieves power-related events from a PAN-OS device. + func getPowerEvents(m *MetricSet) ([]mb.Event, error) { +- + query := "" + var response PowerResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to execute operation: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) ++ } ++ ++ if len(response.Result.Power.Slots) == 0 { ++ m.logger.Warn("No power events found in the response") ++ return nil, nil + } + + events := formatPowerEvents(m, &response) +@@ -35,32 +39,31 @@ func getPowerEvents(m *MetricSet) ([]mb.Event, error) { + } + + func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { +- log := m.Logger() +- events := make([]mb.Event, 0, len(response.Result.Power.Slots)) +- currentTime := time.Now() +- var event mb.Event ++ events := make([]mb.Event, 0) ++ timestamp := time.Now() ++ + for _, slot := range response.Result.Power.Slots { + for _, entry := range slot.Entries { +- log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) +- event = mb.Event{MetricSetFields: mapstr.M{ +- +- "power.slot_number": entry.Slot, +- "power.description": entry.Description, +- "power.alarm": entry.Alarm, +- "power.volts": entry.Volts, +- "power.minimum_volts": entry.MinimumVolts, +- "power.maximum_volts": entry.MaximumVolts, +- }, ++ m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "power.slot_number": entry.Slot, ++ "power.description": entry.Description, ++ "power.alarm": entry.Alarm, ++ "power.volts": entry.Volts, ++ "power.minimum_volts": entry.MinimumVolts, ++ "power.maximum_volts": entry.MaximumVolts, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } ++ events = append(events, event) + } +- +- events = append(events, event) + } + + return events +diff --git a/x-pack/metricbeat/module/panos/system/resources.go b/x-pack/metricbeat/module/panos/system/resources.go +index 1ad18bb92b..6f9a2b6716 100644 +--- a/x-pack/metricbeat/module/panos/system/resources.go ++++ b/x-pack/metricbeat/module/panos/system/resources.go +@@ -16,19 +16,17 @@ import ( + ) + + func getResourceEvents(m *MetricSet) ([]mb.Event, error) { +- var response ResourceResponse + query := "" + +- output, err := m.client.Op(query, vsys, nil, nil) ++ var response ResourceResponse ++ output, err := m.client.Op(query, vsys, nil, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to execute operation: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + + events := formatResourceEvents(m, response.Result) +@@ -62,8 +60,8 @@ MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem + 2 20 0 0 0 0 S 0.0 0.0 0:00.83 kthreadd + */ + func formatResourceEvents(m *MetricSet, input string) []mb.Event { +- currentTime := time.Now() +- events := make([]mb.Event, 0, 1) ++ timestamp := time.Now() ++ events := make([]mb.Event, 0) + + // We only need the top 5 lines + lines := strings.Split(input, "\n") +@@ -75,42 +73,57 @@ func formatResourceEvents(m *MetricSet, input string) []mb.Event { + memoryInfo := parseMemoryInfo(lines[3]) + swapInfo := parseSwapInfo(lines[4]) + +- event := mb.Event{MetricSetFields: mapstr.M{ +- "uptime.days": systemInfo.Uptime.Days, +- "uptime.hours": systemInfo.Uptime.Hours, +- "user_count": systemInfo.UserCount, +- "load_average.1m": systemInfo.LoadAverage.one_minute, +- "load_average.5m": systemInfo.LoadAverage.five_minute, +- "load_average.15m": systemInfo.LoadAverage.fifteen_minute, +- "tasks.total": taskInfo.Total, +- "tasks.running": taskInfo.Running, +- "tasks.sleeping": taskInfo.Sleeping, +- "tasks.stopped": taskInfo.Stopped, +- "tasks.zombie": taskInfo.Zombie, +- "cpu.user": cpuInfo.User, +- "cpu.system": cpuInfo.System, +- "cpu.nice": cpuInfo.Nice, +- "cpu.idle": cpuInfo.Idle, +- "cpu.wait": cpuInfo.Wait, +- "cpu.hi": cpuInfo.Hi, +- "cpu.system_int": cpuInfo.SystemInt, +- "cpu.steal": cpuInfo.Steal, +- "memory.total": memoryInfo.Total, +- "memory.free": memoryInfo.Free, +- "memory.used": memoryInfo.Used, +- "memory.buffer_cache": memoryInfo.BufferCache, +- "swap.total": swapInfo.Total, +- "swap.free": swapInfo.Free, +- "swap.used": swapInfo.Used, +- "swap.available": swapInfo.Available, +- }, ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "uptime": mapstr.M{ ++ "days": systemInfo.Uptime.Days, ++ "hours": systemInfo.Uptime.Hours, ++ "minutes": systemInfo.Uptime.Minutes, ++ }, ++ "user_count": systemInfo.UserCount, ++ "load_average": mapstr.M{ ++ "1m": systemInfo.LoadAverage.OneMinute, ++ "5m": systemInfo.LoadAverage.FiveMinute, ++ "15m": systemInfo.LoadAverage.FifteenMinute, ++ }, ++ "tasks": mapstr.M{ ++ "total": taskInfo.Total, ++ "running": taskInfo.Running, ++ "sleeping": taskInfo.Sleeping, ++ "stopped": taskInfo.Stopped, ++ "zombie": taskInfo.Zombie, ++ }, ++ "cpu": mapstr.M{ ++ "user": cpuInfo.User, ++ "system": cpuInfo.System, ++ "nice": cpuInfo.Nice, ++ "idle": cpuInfo.Idle, ++ "wait": cpuInfo.Wait, ++ "hi": cpuInfo.Hi, ++ "system_int": cpuInfo.SystemInt, ++ "steal": cpuInfo.Steal, ++ }, ++ "memory": mapstr.M{ ++ "total": memoryInfo.Total, ++ "free": memoryInfo.Free, ++ "used": memoryInfo.Used, ++ "buffer_cache": memoryInfo.BufferCache, ++ }, ++ "swap": mapstr.M{ ++ "total": swapInfo.Total, ++ "free": swapInfo.Free, ++ "used": swapInfo.Used, ++ "available": swapInfo.Available, ++ }, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } + + events = append(events, event) + return events +diff --git a/x-pack/metricbeat/module/panos/system/system_types.go b/x-pack/metricbeat/module/panos/system/system_types.go +index d130b9a2e7..4f821477ec 100644 +--- a/x-pack/metricbeat/module/panos/system/system_types.go ++++ b/x-pack/metricbeat/module/panos/system/system_types.go +@@ -15,9 +15,9 @@ type ResourceResponse struct { + } + + type SystemLoad struct { +- one_minute float64 +- five_minute float64 +- fifteen_minute float64 ++ OneMinute float64 ++ FiveMinute float64 ++ FifteenMinute float64 + } + + type Uptime struct { diff --git a/x-pack/metricbeat/patch2.diff b/x-pack/metricbeat/patch2.diff new file mode 100644 index 00000000000..823a6c5bc95 --- /dev/null +++ b/x-pack/metricbeat/patch2.diff @@ -0,0 +1,717 @@ +diff --git a/go.mod b/go.mod +index a47bf7ec15..193648d401 100644 +--- a/go.mod ++++ b/go.mod +@@ -181,6 +181,7 @@ require ( + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.0 + github.com/Azure/azure-storage-blob-go v0.15.0 + github.com/Azure/go-autorest/autorest/adal v0.9.24 ++ github.com/PaloAltoNetworks/pango v0.10.2 + github.com/apache/arrow/go/v14 v14.0.2 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.13 +diff --git a/go.sum b/go.sum +index ec32ee823d..d9ce04d812 100644 +--- a/go.sum ++++ b/go.sum +@@ -215,6 +215,8 @@ github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbV + github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= + github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= + github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= ++github.com/PaloAltoNetworks/pango v0.10.2 h1:Tjn6vIzzAq6Dd7N0mDuiP8w8pz8k5W9zz/TTSUQCsQY= ++github.com/PaloAltoNetworks/pango v0.10.2/go.mod h1:GztcRnVLur7G+VFG7Z5ZKNFgScLtsycwPMp1qVebE5g= + github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= + github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= + github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +diff --git a/x-pack/metricbeat/module/panos/system/certificates.go b/x-pack/metricbeat/module/panos/system/certificates.go +index ca81bfcc91..1ae5c5cf39 100644 +--- a/x-pack/metricbeat/module/panos/system/certificates.go ++++ b/x-pack/metricbeat/module/panos/system/certificates.go +@@ -6,6 +6,8 @@ package system + + import ( + "encoding/xml" ++ "errors" ++ "fmt" + "regexp" + "strings" + "time" +@@ -20,29 +22,39 @@ func getCertificateEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to execute query: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + +- events := formatCertificateEvents(m, response.Result) ++ if response.Result == "" { ++ return nil, fmt.Errorf("empty result from XML response") ++ } ++ ++ events, err := formatCertificateEvents(m, response.Result) ++ if err != nil { ++ return nil, fmt.Errorf("failed to format certificate events: %w", err) ++ } + + return events, nil + } + +-func formatCertificateEvents(m *MetricSet, input string) []mb.Event { +- currentTime := time.Now() ++func formatCertificateEvents(m *MetricSet, input string) ([]mb.Event, error) { ++ timestamp := time.Now() ++ ++ certificates, err := parseCertificates(input) ++ if err != nil { ++ return nil, err ++ } + +- certificates := parseCertificates(input) + events := make([]mb.Event, 0, len(certificates)) + + for _, certificate := range certificates { + event := mb.Event{ ++ Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "certificate.name": certificate.CertName, + "certificate.issuer": certificate.Issuer, +@@ -61,59 +73,78 @@ func formatCertificateEvents(m *MetricSet, input string) []mb.Event { + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } + + events = append(events, event) + } + +- return events ++ return events, nil + } + +-func parseCertificates(input string) []Certificate { ++const ( ++ issuerPrefix = "issuer: " ++ issuerSubjectHashPrefix = "issuer-subjecthash: " ++ issuerKeyHashPrefix = "issuer-keyhash: " ++ dbTypePrefix = "db-type: " ++ dbExpDatePrefix = "db-exp-date: " ++ dbRevDatePrefix = "db-rev-date: " ++ dbSerialNoPrefix = "db-serialno: " ++ dbFilePrefix = "db-file: " ++ dbNamePrefix = "db-name: " ++ dbStatusPrefix = "db-status: " ++) ++ ++func parseCertificates(input string) ([]Certificate, error) { + lines := strings.Split(input, "\n") + pattern := `^[0-9A-Fa-f]{1,40}:[0-9A-Fa-f]{40}([0-9A-Fa-f]{24})?$` + regex := regexp.MustCompile(pattern) +- var certificates []Certificate ++ ++ certificates := make([]Certificate, 0) + var currentSN Certificate + + for _, line := range lines { + line = strings.TrimSpace(line) +- if regex.MatchString(line) { ++ switch { ++ case regex.MatchString(line): + if currentSN.CertName != "" { + certificates = append(certificates, currentSN) + currentSN = Certificate{} + } + currentSN.CertName = line +- } else if strings.HasPrefix(line, "issuer:") { +- currentSN.Issuer = strings.TrimPrefix(line, "issuer: ") +- } else if strings.HasPrefix(line, "issuer-subjecthash:") { +- currentSN.IssuerSubjectHash = strings.TrimPrefix(line, "issuer-subjecthash: ") +- } else if strings.HasPrefix(line, "issuer-keyhash:") { +- currentSN.IssuerKeyHash = strings.TrimPrefix(line, "issuer-keyhash: ") +- if strings.HasPrefix(currentSN.IssuerKeyHash, "issuer-keyhash:") { ++ case strings.HasPrefix(line, issuerPrefix): ++ currentSN.Issuer = strings.TrimPrefix(line, issuerPrefix) ++ case strings.HasPrefix(line, issuerSubjectHashPrefix): ++ currentSN.IssuerSubjectHash = strings.TrimPrefix(line, issuerSubjectHashPrefix) ++ case strings.HasPrefix(line, issuerKeyHashPrefix): ++ currentSN.IssuerKeyHash = strings.TrimPrefix(line, issuerKeyHashPrefix) ++ if strings.HasPrefix(currentSN.IssuerKeyHash, issuerKeyHashPrefix) { + currentSN.IssuerKeyHash = "" + } +- } else if strings.HasPrefix(line, "db-type:") { +- currentSN.DBType = strings.TrimPrefix(line, "db-type: ") +- } else if strings.HasPrefix(line, "db-exp-date:") { +- currentSN.DBExpDate = strings.TrimPrefix(line, "db-exp-date: ") +- } else if strings.HasPrefix(line, "db-rev-date:") { +- currentSN.DBRevDate = strings.TrimPrefix(line, "db-rev-date: ") +- } else if strings.HasPrefix(line, "db-serialno:") { +- currentSN.DBSerialNo = strings.TrimPrefix(line, "db-serialno: ") +- } else if strings.HasPrefix(line, "db-file:") { +- currentSN.DBFile = strings.TrimPrefix(line, "db-file: ") +- } else if strings.HasPrefix(line, "db-name:") { +- currentSN.DBName = strings.TrimPrefix(line, "db-name: ") +- } else if strings.HasPrefix(line, "db-status:") { +- currentSN.DBStatus = strings.TrimPrefix(line, "db-status: ") ++ case strings.HasPrefix(line, dbTypePrefix): ++ currentSN.DBType = strings.TrimPrefix(line, dbTypePrefix) ++ case strings.HasPrefix(line, dbExpDatePrefix): ++ currentSN.DBExpDate = strings.TrimPrefix(line, dbExpDatePrefix) ++ case strings.HasPrefix(line, dbRevDatePrefix): ++ currentSN.DBRevDate = strings.TrimPrefix(line, dbRevDatePrefix) ++ case strings.HasPrefix(line, dbSerialNoPrefix): ++ currentSN.DBSerialNo = strings.TrimPrefix(line, dbSerialNoPrefix) ++ case strings.HasPrefix(line, dbFilePrefix): ++ currentSN.DBFile = strings.TrimPrefix(line, dbFilePrefix) ++ case strings.HasPrefix(line, dbNamePrefix): ++ currentSN.DBName = strings.TrimPrefix(line, dbNamePrefix) ++ case strings.HasPrefix(line, dbStatusPrefix): ++ currentSN.DBStatus = strings.TrimPrefix(line, dbStatusPrefix) + } + } + +- if currentSN.Issuer != "" { ++ if currentSN.CertName != "" { + certificates = append(certificates, currentSN) + } + +- return certificates ++ if len(certificates) == 0 { ++ return nil, errors.New("no valid certificates found") ++ } ++ ++ return certificates, nil + } +diff --git a/x-pack/metricbeat/module/panos/system/fans.go b/x-pack/metricbeat/module/panos/system/fans.go +index 3e04299b2f..b725d83966 100644 +--- a/x-pack/metricbeat/module/panos/system/fans.go ++++ b/x-pack/metricbeat/module/panos/system/fans.go +@@ -6,6 +6,7 @@ package system + + import ( + "encoding/xml" ++ "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" +@@ -18,46 +19,46 @@ func getFanEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error querying fan data: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error unmarshaling fan data: %w", err) + } + +- events := formatFanEvents(m, &response) +- +- return events, nil ++ return formatFanEvents(m, &response), nil + } + + func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { +- log := m.Logger() +- events := make([]mb.Event, 0, len(response.Result.Fan.Slots)) +- currentTime := time.Now() +- var event mb.Event ++ if response == nil || len(response.Result.Fan.Slots) == 0 { ++ return nil ++ } ++ ++ events := make([]mb.Event, 0) ++ timestamp := time.Now() ++ + for _, slot := range response.Result.Fan.Slots { + for _, entry := range slot.Entries { +- log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) +- event = mb.Event{MetricSetFields: mapstr.M{ +- "fan.slot_number": entry.Slot, +- "fan.description": entry.Description, +- "fan.alarm": entry.Alarm, +- "fan.rpm": entry.RPMs, +- "fan.min_rpm": entry.Min, +- }, ++ m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "fan.slot_number": entry.Slot, ++ "fan.description": entry.Description, ++ "fan.alarm": entry.Alarm, ++ "fan.rpm": entry.RPMs, ++ "fan.min_rpm": entry.Min, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } ++ events = append(events, event) + } +- +- events = append(events, event) + } + + return events +diff --git a/x-pack/metricbeat/module/panos/system/filesystem.go b/x-pack/metricbeat/module/panos/system/filesystem.go +index 4adc63c3dc..e75eac63ef 100644 +--- a/x-pack/metricbeat/module/panos/system/filesystem.go ++++ b/x-pack/metricbeat/module/panos/system/filesystem.go +@@ -6,6 +6,7 @@ package system + + import ( + "encoding/xml" ++ "fmt" + "strings" + "time" + +@@ -20,39 +21,38 @@ func getFilesystemEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error querying filesystem info: %w", err) ++ } ++ ++ if len(output) == 0 { ++ return nil, fmt.Errorf("received empty output from filesystem query") + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error unmarshaling filesystem response: %w", err) + } + + filesystems := getFilesystems(response.Result.Data) +- events := formatFilesytemEvents(m, filesystems) ++ events := formatFilesystemEvents(m, filesystems) + + return events, nil + } + +-/* +-Result from the XML API call is basically linux df -h output: +-Filesystem Size Used Avail Use% Mounted on +-/dev/root 9.5G 4.0G 5.1G 44% / +-none 2.5G 64K 2.5G 1% /dev +-/dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg +-/dev/sda6 7.6G 3.1G 4.2G 43% /opt/panrepo +-tmpfs 2.5G 399M 2.1G 16% /dev/shm +-cgroup_root 2.5G 0 2.5G 0% /cgroup +-/dev/sda8 173G 63G 102G 39% /opt/panlogs +-tmpfs 12M 44K 12M 1% /opt/pancfg/mgmt/ssl/private +-*/ + func getFilesystems(input string) []Filesystem { + lines := strings.Split(input, "\n") + filesystems := make([]Filesystem, 0) + +- // Skip the first line which is the header ++ // Skip the first line which is the header: ++ // ++ // Example: ++ // Result from the XML API call is basically a command in Linux distribution i.e., "df -h"'s output: ++ // ++ // Filesystem Size Used Avail Use% Mounted on ++ // /dev/root 9.5G 4.0G 5.1G 44% / ++ // none 2.5G 64K 2.5G 1% /dev ++ // /dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg ++ // + for _, line := range lines[1:] { + fields := strings.Fields(line) + if len(fields) == 6 { +@@ -70,31 +70,35 @@ func getFilesystems(input string) []Filesystem { + return filesystems + } + +-func formatFilesytemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { +- events := make([]mb.Event, 0, len(filesystems)) ++func formatFilesystemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { ++ if len(filesystems) == 0 { ++ return nil ++ } + +- currentTime := time.Now() ++ events := make([]mb.Event, 0, len(filesystems)) ++ timestamp := time.Now() + + for _, filesystem := range filesystems { +- event := mb.Event{MetricSetFields: mapstr.M{ +- "filesystem.name": filesystem.Name, +- "filesystem.size": filesystem.Size, +- "filesystem.used": filesystem.Used, +- "filesystem.available": filesystem.Avail, +- "filesystem.use_percent": filesystem.UsePerc, +- "filesystem.mounted": filesystem.Mounted, +- }, ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "filesystem.name": filesystem.Name, ++ "filesystem.size": filesystem.Size, ++ "filesystem.used": filesystem.Used, ++ "filesystem.available": filesystem.Avail, ++ "filesystem.use_percent": filesystem.UsePerc, ++ "filesystem.mounted": filesystem.Mounted, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } + + events = append(events, event) + } + + return events +- + } +diff --git a/x-pack/metricbeat/module/panos/system/license.go b/x-pack/metricbeat/module/panos/system/license.go +index d12f03b8c1..88ae64050d 100644 +--- a/x-pack/metricbeat/module/panos/system/license.go ++++ b/x-pack/metricbeat/module/panos/system/license.go +@@ -6,6 +6,7 @@ package system + + import ( + "encoding/xml" ++ "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" +@@ -18,48 +19,52 @@ func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to execute query: %w", err) ++ } ++ ++ if len(output) == 0 { ++ return nil, fmt.Errorf("empty response from PanOS") + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + +- events := formatLicenseEvents(m, response.Result.Licenses) +- +- return events, nil ++ if len(response.Result.Licenses) == 0 { ++ m.logger.Warn("No licenses found in the response") ++ return nil, nil ++ } + ++ return formatLicenseEvents(m, response.Result.Licenses), nil + } + + func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { + events := make([]mb.Event, 0, len(licenses)) +- +- currentTime := time.Now() ++ timestamp := time.Now() + + for _, license := range licenses { +- event := mb.Event{MetricSetFields: mapstr.M{ +- "license.feature": license.Feature, +- "license.escription": license.Description, +- "license.serial": license.Serial, +- "license.issued": license.Issued, +- "license.expires": license.Expires, +- "license.expired": license.Expired, +- "license.auth_code": license.AuthCode, +- }, ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "license.feature": license.Feature, ++ "license.description": license.Description, // Fixed typo ++ "license.serial": license.Serial, ++ "license.issued": license.Issued, ++ "license.expires": license.Expires, ++ "license.expired": license.Expired, ++ "license.auth_code": license.AuthCode, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } + + events = append(events, event) + } + + return events +- + } +diff --git a/x-pack/metricbeat/module/panos/system/power.go b/x-pack/metricbeat/module/panos/system/power.go +index d5a4aa8487..a7540ad618 100644 +--- a/x-pack/metricbeat/module/panos/system/power.go ++++ b/x-pack/metricbeat/module/panos/system/power.go +@@ -6,27 +6,31 @@ package system + + import ( + "encoding/xml" ++ "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" + ) + ++// getPowerEvents retrieves power-related events from a PAN-OS device. + func getPowerEvents(m *MetricSet) ([]mb.Event, error) { +- + query := "" + var response PowerResponse + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to execute operation: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) ++ } ++ ++ if len(response.Result.Power.Slots) == 0 { ++ m.logger.Warn("No power events found in the response") ++ return nil, nil + } + + events := formatPowerEvents(m, &response) +@@ -35,32 +39,31 @@ func getPowerEvents(m *MetricSet) ([]mb.Event, error) { + } + + func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { +- log := m.Logger() +- events := make([]mb.Event, 0, len(response.Result.Power.Slots)) +- currentTime := time.Now() +- var event mb.Event ++ events := make([]mb.Event, 0) ++ timestamp := time.Now() ++ + for _, slot := range response.Result.Power.Slots { + for _, entry := range slot.Entries { +- log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) +- event = mb.Event{MetricSetFields: mapstr.M{ +- +- "power.slot_number": entry.Slot, +- "power.description": entry.Description, +- "power.alarm": entry.Alarm, +- "power.volts": entry.Volts, +- "power.minimum_volts": entry.MinimumVolts, +- "power.maximum_volts": entry.MaximumVolts, +- }, ++ m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "power.slot_number": entry.Slot, ++ "power.description": entry.Description, ++ "power.alarm": entry.Alarm, ++ "power.volts": entry.Volts, ++ "power.minimum_volts": entry.MinimumVolts, ++ "power.maximum_volts": entry.MaximumVolts, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } ++ events = append(events, event) + } +- +- events = append(events, event) + } + + return events +diff --git a/x-pack/metricbeat/module/panos/system/resources.go b/x-pack/metricbeat/module/panos/system/resources.go +index 1ad18bb92b..6f9a2b6716 100644 +--- a/x-pack/metricbeat/module/panos/system/resources.go ++++ b/x-pack/metricbeat/module/panos/system/resources.go +@@ -16,19 +16,17 @@ import ( + ) + + func getResourceEvents(m *MetricSet) ([]mb.Event, error) { +- var response ResourceResponse + query := "" + +- output, err := m.client.Op(query, vsys, nil, nil) ++ var response ResourceResponse ++ output, err := m.client.Op(query, vsys, nil, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to execute operation: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) + } + + events := formatResourceEvents(m, response.Result) +@@ -62,8 +60,8 @@ MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem + 2 20 0 0 0 0 S 0.0 0.0 0:00.83 kthreadd + */ + func formatResourceEvents(m *MetricSet, input string) []mb.Event { +- currentTime := time.Now() +- events := make([]mb.Event, 0, 1) ++ timestamp := time.Now() ++ events := make([]mb.Event, 0) + + // We only need the top 5 lines + lines := strings.Split(input, "\n") +@@ -75,42 +73,57 @@ func formatResourceEvents(m *MetricSet, input string) []mb.Event { + memoryInfo := parseMemoryInfo(lines[3]) + swapInfo := parseSwapInfo(lines[4]) + +- event := mb.Event{MetricSetFields: mapstr.M{ +- "uptime.days": systemInfo.Uptime.Days, +- "uptime.hours": systemInfo.Uptime.Hours, +- "user_count": systemInfo.UserCount, +- "load_average.1m": systemInfo.LoadAverage.one_minute, +- "load_average.5m": systemInfo.LoadAverage.five_minute, +- "load_average.15m": systemInfo.LoadAverage.fifteen_minute, +- "tasks.total": taskInfo.Total, +- "tasks.running": taskInfo.Running, +- "tasks.sleeping": taskInfo.Sleeping, +- "tasks.stopped": taskInfo.Stopped, +- "tasks.zombie": taskInfo.Zombie, +- "cpu.user": cpuInfo.User, +- "cpu.system": cpuInfo.System, +- "cpu.nice": cpuInfo.Nice, +- "cpu.idle": cpuInfo.Idle, +- "cpu.wait": cpuInfo.Wait, +- "cpu.hi": cpuInfo.Hi, +- "cpu.system_int": cpuInfo.SystemInt, +- "cpu.steal": cpuInfo.Steal, +- "memory.total": memoryInfo.Total, +- "memory.free": memoryInfo.Free, +- "memory.used": memoryInfo.Used, +- "memory.buffer_cache": memoryInfo.BufferCache, +- "swap.total": swapInfo.Total, +- "swap.free": swapInfo.Free, +- "swap.used": swapInfo.Used, +- "swap.available": swapInfo.Available, +- }, ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "uptime": mapstr.M{ ++ "days": systemInfo.Uptime.Days, ++ "hours": systemInfo.Uptime.Hours, ++ "minutes": systemInfo.Uptime.Minutes, ++ }, ++ "user_count": systemInfo.UserCount, ++ "load_average": mapstr.M{ ++ "1m": systemInfo.LoadAverage.OneMinute, ++ "5m": systemInfo.LoadAverage.FiveMinute, ++ "15m": systemInfo.LoadAverage.FifteenMinute, ++ }, ++ "tasks": mapstr.M{ ++ "total": taskInfo.Total, ++ "running": taskInfo.Running, ++ "sleeping": taskInfo.Sleeping, ++ "stopped": taskInfo.Stopped, ++ "zombie": taskInfo.Zombie, ++ }, ++ "cpu": mapstr.M{ ++ "user": cpuInfo.User, ++ "system": cpuInfo.System, ++ "nice": cpuInfo.Nice, ++ "idle": cpuInfo.Idle, ++ "wait": cpuInfo.Wait, ++ "hi": cpuInfo.Hi, ++ "system_int": cpuInfo.SystemInt, ++ "steal": cpuInfo.Steal, ++ }, ++ "memory": mapstr.M{ ++ "total": memoryInfo.Total, ++ "free": memoryInfo.Free, ++ "used": memoryInfo.Used, ++ "buffer_cache": memoryInfo.BufferCache, ++ }, ++ "swap": mapstr.M{ ++ "total": swapInfo.Total, ++ "free": swapInfo.Free, ++ "used": swapInfo.Used, ++ "available": swapInfo.Available, ++ }, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } + + events = append(events, event) + return events +diff --git a/x-pack/metricbeat/module/panos/system/system_types.go b/x-pack/metricbeat/module/panos/system/system_types.go +index d130b9a2e7..4f821477ec 100644 +--- a/x-pack/metricbeat/module/panos/system/system_types.go ++++ b/x-pack/metricbeat/module/panos/system/system_types.go +@@ -15,9 +15,9 @@ type ResourceResponse struct { + } + + type SystemLoad struct { +- one_minute float64 +- five_minute float64 +- fifteen_minute float64 ++ OneMinute float64 ++ FiveMinute float64 ++ FifteenMinute float64 + } + + type Uptime struct { diff --git a/x-pack/metricbeat/x.diff b/x-pack/metricbeat/x.diff new file mode 100644 index 00000000000..c739264906e --- /dev/null +++ b/x-pack/metricbeat/x.diff @@ -0,0 +1,429 @@ +diff --git a/go.mod b/go.mod +index a47bf7ec15..193648d401 100644 +--- a/go.mod ++++ b/go.mod +@@ -181,6 +181,7 @@ require ( + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.0 + github.com/Azure/azure-storage-blob-go v0.15.0 + github.com/Azure/go-autorest/autorest/adal v0.9.24 ++ github.com/PaloAltoNetworks/pango v0.10.2 + github.com/apache/arrow/go/v14 v14.0.2 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.13 +diff --git a/go.sum b/go.sum +index ec32ee823d..d9ce04d812 100644 +--- a/go.sum ++++ b/go.sum +@@ -215,6 +215,8 @@ github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbV + github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= + github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= + github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= ++github.com/PaloAltoNetworks/pango v0.10.2 h1:Tjn6vIzzAq6Dd7N0mDuiP8w8pz8k5W9zz/TTSUQCsQY= ++github.com/PaloAltoNetworks/pango v0.10.2/go.mod h1:GztcRnVLur7G+VFG7Z5ZKNFgScLtsycwPMp1qVebE5g= + github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= + github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= + github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +diff --git a/x-pack/metricbeat/module/panos/client.go b/x-pack/metricbeat/module/panos/client.go +index a781b99871..e01cd941d7 100644 +--- a/x-pack/metricbeat/module/panos/client.go ++++ b/x-pack/metricbeat/module/panos/client.go +@@ -6,6 +6,7 @@ package panos + + import ( + "flag" ++ "fmt" + + "github.com/PaloAltoNetworks/pango" + ) +@@ -37,7 +38,7 @@ func GetPanosClient(config *Config) (PanosClient, error) { + firewall := pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + err := firewall.Initialize() + if err != nil { +- return nil, err ++ return nil, fmt.Errorf("error initializing firewall client: %w", err) + } + // Instantiate PanosFirewallClient + return &PanosFirewallClient{Firewall: firewall}, nil +diff --git a/x-pack/metricbeat/module/panos/vpn/gp_sessions.go b/x-pack/metricbeat/module/panos/vpn/gp_sessions.go +index ea1b8c31b6..af7d858fa1 100644 +--- a/x-pack/metricbeat/module/panos/vpn/gp_sessions.go ++++ b/x-pack/metricbeat/module/panos/vpn/gp_sessions.go +@@ -6,73 +6,77 @@ package vpn + + import ( + "encoding/xml" ++ "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/elastic-agent-libs/mapstr" + ) + ++const gpSessionsQuery = "" ++ + func getGlobalProtectSessionEvents(m *MetricSet) ([]mb.Event, error) { +- query := "" + var response GPSessionsResponse + +- output, err := m.client.Op(query, vsys, nil, nil) ++ output, err := m.client.Op(gpSessionsQuery, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error querying GlobalProtect sessions: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error unmarshaling GlobalProtect sessions response: %w", err) + } + + events := formatGPSessionEvents(m, response.Result.Sessions) + + return events, nil +- + } + + func formatGPSessionEvents(m *MetricSet, sessions []GPSession) []mb.Event { +- events := make([]mb.Event, 0, len(sessions)) ++ if sessions == nil { ++ return nil ++ } + +- currentTime := time.Now() ++ events := make([]mb.Event, 0, len(sessions)) ++ timestamp := time.Now() + + for _, session := range sessions { +- event := mb.Event{MetricSetFields: mapstr.M{ +- "globalprotect.domain": session.Domain, +- "globalprotect.is_local": session.IsLocal, +- "globalprotect.username": session.Username, +- "globalprotect.rimary_username": session.PrimaryUsername, +- "globalprotect.region_for_config": session.RegionForConfig, +- "globalprotect.ource_region": session.SourceRegion, +- "globalprotect.computer": session.Computer, +- "globalprotect.client": session.Client, +- "globalprotect.vpn_type": session.VPNType, +- "globalprotect.host_id": session.HostID, +- "globalprotect.app_version": session.AppVersion, +- "globalprotect.virtual_ip": session.VirtualIP, +- "globalprotect.virtual_ipv6": session.VirtualIPv6, +- "globalprotect.public_ip": session.PublicIP, +- "globalprotect.public_ipv6": session.PublicIPv6, +- "globalprotect.tunnel_type": session.TunnelType, +- "globalprotect.public_connection_ipv6": session.PublicConnectionIPv6, +- "globalprotect.lient_ip": session.ClientIP, +- "globalprotect.login_time": session.LoginTime, +- "globalprotect.login_time_utc": session.LoginTimeUTC, +- "globalprotect.lifetime": session.Lifetime, +- "globalprotect.request_login": session.RequestLogin, +- "globalprotect.request_get_config": session.RequestGetConfig, +- "globalprotect.request_sslvpn_connect": session.RequestSSLVPNConnect, +- }, ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "globalprotect.domain": session.Domain, ++ "globalprotect.is_local": session.IsLocal, ++ "globalprotect.username": session.Username, ++ "globalprotect.primary_username": session.PrimaryUsername, ++ "globalprotect.region_for_config": session.RegionForConfig, ++ "globalprotect.source_region": session.SourceRegion, ++ "globalprotect.computer": session.Computer, ++ "globalprotect.client": session.Client, ++ "globalprotect.vpn_type": session.VPNType, ++ "globalprotect.host_id": session.HostID, ++ "globalprotect.app_version": session.AppVersion, ++ "globalprotect.virtual_ip": session.VirtualIP, ++ "globalprotect.virtual_ipv6": session.VirtualIPv6, ++ "globalprotect.public_ip": session.PublicIP, ++ "globalprotect.public_ipv6": session.PublicIPv6, ++ "globalprotect.tunnel_type": session.TunnelType, ++ "globalprotect.public_connection_ipv6": session.PublicConnectionIPv6, ++ "globalprotect.client_ip": session.ClientIP, ++ "globalprotect.login_time": session.LoginTime, ++ "globalprotect.login_time_utc": session.LoginTimeUTC, ++ "globalprotect.lifetime": session.Lifetime, ++ "globalprotect.request_login": session.RequestLogin, ++ "globalprotect.request_get_config": session.RequestGetConfig, ++ "globalprotect.request_sslvpn_connect": session.RequestSSLVPNConnect, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} ++ }, ++ } + + events = append(events, event) + } +diff --git a/x-pack/metricbeat/module/panos/vpn/gp_stats.go b/x-pack/metricbeat/module/panos/vpn/gp_stats.go +index f7177fe300..5907d784f2 100644 +--- a/x-pack/metricbeat/module/panos/vpn/gp_stats.go ++++ b/x-pack/metricbeat/module/panos/vpn/gp_stats.go +@@ -6,6 +6,7 @@ package vpn + + import ( + "encoding/xml" ++ "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" +@@ -18,45 +19,48 @@ func getGlobalProtectStatsEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error querying GlobalProtect statistics: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error unmarshaling GlobalProtect statistics response: %w", err) + } + + events := formatGPStatsEvents(m, response) + + return events, nil +- + } + + func formatGPStatsEvents(m *MetricSet, response GPStatsResponse) []mb.Event { ++ if len(response.Result.Gateways) == 0 { ++ return nil ++ } ++ + events := make([]mb.Event, 0, len(response.Result.Gateways)) + +- currentTime := time.Now() ++ timestamp := time.Now() + totalCurrent := response.Result.TotalCurrentUsers + totalPrevious := response.Result.TotalPreviousUsers + + for _, gateway := range response.Result.Gateways { +- event := mb.Event{MetricSetFields: mapstr.M{ +- "globalprotect.gateway.name": gateway.Name, +- "globalprotect.gateway.current_users": gateway.CurrentUsers, +- "globalprotect.gateway.previous_users": gateway.PreviousUsers, +- "globalprotect.total_current_users": totalCurrent, +- "globalprotect.total_previous_users": totalPrevious, +- }, ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "globalprotect.gateway.name": gateway.Name, ++ "globalprotect.gateway.current_users": gateway.CurrentUsers, ++ "globalprotect.gateway.previous_users": gateway.PreviousUsers, ++ "globalprotect.total_current_users": totalCurrent, ++ "globalprotect.total_previous_users": totalPrevious, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} +- ++ }, ++ } + events = append(events, event) + } + +diff --git a/x-pack/metricbeat/module/panos/vpn/tunnels.go b/x-pack/metricbeat/module/panos/vpn/tunnels.go +index 8dcb13a79e..1d22cc2625 100644 +--- a/x-pack/metricbeat/module/panos/vpn/tunnels.go ++++ b/x-pack/metricbeat/module/panos/vpn/tunnels.go +@@ -6,6 +6,7 @@ package vpn + + import ( + "encoding/xml" ++ "fmt" + "time" + + "github.com/elastic/beats/v7/metricbeat/mb" +@@ -18,59 +19,55 @@ func getIPSecTunnelEvents(m *MetricSet) ([]mb.Event, error) { + + output, err := m.client.Op(query, vsys, nil, nil) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error querying IPSec tunnels: %w", err) + } + + err = xml.Unmarshal(output, &response) + if err != nil { +- m.logger.Error("Error: %s", err) +- return nil, err ++ return nil, fmt.Errorf("error unmarshaling IPSec tunnels response: %w", err) + } + +- events := getEvents(m, response.Result.Entries) ++ events := formatIPSecTunnelEvents(m, response.Result.Entries) + + return events, nil +- + } + +-func getEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { ++func formatIPSecTunnelEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { + events := make([]mb.Event, 0, len(entries)) +- +- currentTime := time.Now() ++ timestamp := time.Now() + + for _, entry := range entries { +- event := mb.Event{MetricSetFields: mapstr.M{ +- "ipsec_tunnel.id": entry.ID, +- "ipsec_tunnel.name": entry.Name, +- "ipsec_tunnel.gw": entry.GW, +- "ipsec_tunnel.TSi_ip": entry.TSiIP, +- "ipsec_tunnel.TSi_prefix": entry.TSiPrefix, +- "ipsec_tunnel.TSi_proto": entry.TSiProto, +- "ipsec_tunnel.TSi_port": entry.TSiPort, +- "ipsec_tunnel.TSr_ip": entry.TSrIP, +- "ipsec_tunnel.TSr_prefix": entry.TSrPrefix, +- "ipsec_tunnel.TSr_proto": entry.TSrProto, +- "ipsec_tunnel.TSr_port": entry.TSrPort, +- "ipsec_tunnel.proto": entry.Proto, +- "ipsec_tunnel.mode": entry.Mode, +- "ipsec_tunnel.dh": entry.DH, +- "ipsec_tunnel.enc": entry.Enc, +- "ipsec_tunnel.hash": entry.Hash, +- "ipsec_tunnel.life": entry.Life, +- "ipsec_tunnel.kb": entry.KB, +- }, ++ event := mb.Event{ ++ Timestamp: timestamp, ++ MetricSetFields: mapstr.M{ ++ "ipsec_tunnel.id": entry.ID, ++ "ipsec_tunnel.name": entry.Name, ++ "ipsec_tunnel.gw": entry.GW, ++ "ipsec_tunnel.TSi_ip": entry.TSiIP, ++ "ipsec_tunnel.TSi_prefix": entry.TSiPrefix, ++ "ipsec_tunnel.TSi_proto": entry.TSiProto, ++ "ipsec_tunnel.TSi_port": entry.TSiPort, ++ "ipsec_tunnel.TSr_ip": entry.TSrIP, ++ "ipsec_tunnel.TSr_prefix": entry.TSrPrefix, ++ "ipsec_tunnel.TSr_proto": entry.TSrProto, ++ "ipsec_tunnel.TSr_port": entry.TSrPort, ++ "ipsec_tunnel.proto": entry.Proto, ++ "ipsec_tunnel.mode": entry.Mode, ++ "ipsec_tunnel.dh": entry.DH, ++ "ipsec_tunnel.enc": entry.Enc, ++ "ipsec_tunnel.hash": entry.Hash, ++ "ipsec_tunnel.life": entry.Life, ++ "ipsec_tunnel.kb": entry.KB, ++ }, + RootFields: mapstr.M{ + "observer.ip": m.config.HostIp, + "host.ip": m.config.HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", +- "@Timestamp": currentTime, +- }} +- ++ }, ++ } + events = append(events, event) + } + + return events +- + } +diff --git a/x-pack/metricbeat/module/panos/vpn/vpn.go b/x-pack/metricbeat/module/panos/vpn/vpn.go +index e3f428bbf5..d7582951c6 100644 +--- a/x-pack/metricbeat/module/panos/vpn/vpn.go ++++ b/x-pack/metricbeat/module/panos/vpn/vpn.go +@@ -6,7 +6,7 @@ package vpn + + import ( + "errors" +- "strings" ++ "fmt" + + "github.com/elastic/beats/v7/libbeat/common/cfgwarn" + "github.com/elastic/beats/v7/metricbeat/mb" +@@ -50,7 +50,6 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + + logger := logp.NewLogger(base.FullyQualifiedName()) + +- //client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + client, err := panos.GetPanosClient(config) + if err != nil { + return nil, err +@@ -68,44 +67,31 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + // format. It publishes the event which is then forwarded to the output. In case + // of an error set the Error field of mb.Event or simply call report.Error(). + func (m *MetricSet) Fetch(report mb.ReporterV2) error { +- // accumulate errs and report them all at the end so that we don't +- // stop processing events if one of the fetches fails +- var errs []string +- +- gpSessionEvents, err := getGlobalProtectSessionEvents(m) +- if err != nil { +- m.logger.Error("Error get GlobalProtect session events: %s", err) +- errs = append(errs, err.Error()) +- } +- +- for _, event := range gpSessionEvents { +- report.Event(event) +- } +- +- gpStatsEvents, err := getGlobalProtectStatsEvents(m) +- if err != nil { +- m.logger.Error("Error get GlobalProtect stats events: %s", err) +- errs = append(errs, err.Error()) ++ var errs []error ++ ++ eventFetchers := []struct { ++ name string ++ fn func(*MetricSet) ([]mb.Event, error) ++ }{ ++ {"globalprotect session", getGlobalProtectSessionEvents}, ++ {"globalprotect stats", getGlobalProtectStatsEvents}, ++ {"ipsec tunnel", getIPSecTunnelEvents}, + } + +- for _, event := range gpStatsEvents { +- report.Event(event) +- } +- +- ipsecTunnelsEvents, err := getIPSecTunnelEvents(m) +- if err != nil { +- m.logger.Error("Error get IPSec Tunnel events: %s", err) +- errs = append(errs, err.Error()) +- } +- +- for _, event := range ipsecTunnelsEvents { +- report.Event(event) ++ for _, fetcher := range eventFetchers { ++ events, err := fetcher.fn(m) ++ if err != nil { ++ m.logger.Errorf("Error getting %s events: %s", fetcher.name, err) ++ errs = append(errs, err) ++ } else { ++ for _, event := range events { ++ report.Event(event) ++ } ++ } + } + + if len(errs) > 0 { +- return errors.New(strings.Join(errs, "; ")) +- } else { +- return nil ++ return fmt.Errorf("error while fetching vpn metrics: %w", errors.Join(errs...)) + } +- ++ return nil + } From 6a9c0f5c20b138a59d96778e246807db8f16f6b4 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Tue, 10 Sep 2024 18:21:45 -0400 Subject: [PATCH 20/32] more PR comments addressed. Still to do: tests --- x-pack/metricbeat/metricbeat.reference.yml | 4 +- .../metricbeat/module/panw/_meta/config.yml | 2 +- .../module/panw/_meta/docs.asciidoc | 10 +- .../metricbeat/module/panw/_meta/fields.yml | 8 +- x-pack/metricbeat/module/panw/client.go | 6 +- x-pack/metricbeat/module/panw/config.go | 1 + x-pack/metricbeat/module/panw/fields.go | 2 +- .../module/panw/interfaces/_meta/data.json | 4 +- .../panw/interfaces/_meta/docs.asciidoc | 2 +- .../module/panw/interfaces/_meta/fields.yml | 8 +- .../module/panw/interfaces/ha_interfaces.go | 16 +- .../panw/interfaces/ifnet_interfaces.go | 3 +- .../module/panw/interfaces/interfaces.go | 1 - .../module/panw/routing/_meta/data.json | 4 +- .../module/panw/routing/_meta/docs.asciidoc | 2 +- .../module/panw/routing/_meta/fields.yml | 80 +- .../module/panw/routing/bgp_peers.go | 121 ++- .../metricbeat/module/panw/routing/routing.go | 1 - .../module/panw/system/_meta/data.json | 4 +- .../module/panw/system/_meta/docs.asciidoc | 2 +- .../module/panw/system/_meta/fields.yml | 32 +- .../module/panw/system/certificates.go | 3 +- x-pack/metricbeat/module/panw/system/fans.go | 9 +- .../module/panw/system/filesystem.go | 71 +- .../metricbeat/module/panw/system/license.go | 23 +- x-pack/metricbeat/module/panw/system/power.go | 3 +- .../module/panw/system/resources.go | 19 +- .../module/panw/system/system_types.go | 2 +- .../metricbeat/module/panw/system/thermal.go | 9 +- x-pack/metricbeat/module/panw/util.go | 9 +- .../module/panw/vpn/_meta/data.json | 4 +- .../module/panw/vpn/_meta/docs.asciidoc | 2 +- .../module/panw/vpn/_meta/fields.yml | 18 +- .../metricbeat/module/panw/vpn/gp_sessions.go | 13 +- x-pack/metricbeat/module/panw/vpn/gp_stats.go | 3 +- x-pack/metricbeat/module/panw/vpn/tunnels.go | 3 +- x-pack/metricbeat/modules.d/panw.yml.disabled | 7 +- x-pack/metricbeat/patch1.diff | 717 ------------------ x-pack/metricbeat/patch2.diff | 717 ------------------ x-pack/metricbeat/x.diff | 429 ----------- 40 files changed, 327 insertions(+), 2047 deletions(-) delete mode 100644 x-pack/metricbeat/patch1.diff delete mode 100644 x-pack/metricbeat/patch2.diff delete mode 100644 x-pack/metricbeat/x.diff diff --git a/x-pack/metricbeat/metricbeat.reference.yml b/x-pack/metricbeat/metricbeat.reference.yml index 7ba66745ac7..02e0e8fe90e 100644 --- a/x-pack/metricbeat/metricbeat.reference.yml +++ b/x-pack/metricbeat/metricbeat.reference.yml @@ -1268,8 +1268,8 @@ metricbeat.modules: # username: "" # password: "" -#-------------------------------- Panos Module -------------------------------- -- module: panos +#--------------------------------- Panw Module --------------------------------- +- module: panw metricsets: ["licenses"] enabled: false period: 10s diff --git a/x-pack/metricbeat/module/panw/_meta/config.yml b/x-pack/metricbeat/module/panw/_meta/config.yml index 70cc179e254..9a68d01f798 100644 --- a/x-pack/metricbeat/module/panw/_meta/config.yml +++ b/x-pack/metricbeat/module/panw/_meta/config.yml @@ -1,4 +1,4 @@ -- module: panos +- module: panw metricsets: ["licenses"] enabled: false period: 10s diff --git a/x-pack/metricbeat/module/panw/_meta/docs.asciidoc b/x-pack/metricbeat/module/panw/_meta/docs.asciidoc index a800635bf4e..f74449adf0f 100644 --- a/x-pack/metricbeat/module/panw/_meta/docs.asciidoc +++ b/x-pack/metricbeat/module/panw/_meta/docs.asciidoc @@ -1,10 +1,10 @@ -:modulename: panos +:modulename: panw include::{libbeat-dir}/shared/integration-link.asciidoc[] :modulename!: -The panos Metricbeat module uses the Palo Alto [pango](https://pkg.go.dev/github.com/PaloAltoNetworks/pango#section-documentation) package to extract metrics +The panw Metricbeat module uses the Palo Alto [pango](https://pkg.go.dev/github.com/PaloAltoNetworks/pango#section-documentation) package to extract metrics information from a firewall device via the XML API. [float] @@ -14,15 +14,15 @@ information from a firewall device via the XML API. [float] === Module-specific configuration notes -The panos module configuration requires the ip address of the target firewall device and an API Key generated from that firewall. It is assumed -that network access to the firewall is available. All access by the panos module is read-only. +The panw module configuration requires the ip address of the target firewall device and an API Key generated from that firewall. It is assumed +that network access to the firewall is available. All access by the panw module is read-only. ***Limitations*** The current version of the module is configured to run against **exactly 1** firewall. Multiple firewalls will require multiple agent configurations. The module has also not been tested with Panorama, though it should work since it only relies on lower level Client.Op calls to send XML API commands to the server. -Required credentials for the `panos` module: +Required credentials for the `panw` module: `host_ip` :: IP address of the firewall - must be network accessible. diff --git a/x-pack/metricbeat/module/panw/_meta/fields.yml b/x-pack/metricbeat/module/panw/_meta/fields.yml index 52e2568926b..2296a368bab 100644 --- a/x-pack/metricbeat/module/panw/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/_meta/fields.yml @@ -1,10 +1,10 @@ -- key: panos - title: "panos" +- key: panw + title: "panw" release: beta description: > - panos module + panw module fields: - - name: panos + - name: panw type: group description: > fields: diff --git a/x-pack/metricbeat/module/panw/client.go b/x-pack/metricbeat/module/panw/client.go index 866862516aa..6ac3161c148 100644 --- a/x-pack/metricbeat/module/panw/client.go +++ b/x-pack/metricbeat/module/panw/client.go @@ -11,6 +11,10 @@ import ( "github.com/PaloAltoNetworks/pango" ) +// Vsys is the virtual system to query. If empty, the default vsys is used. This is a placeholder for future use, +// as the module currently only supports the default vsys. +const Vsys = "" + // PanwClient interface with an Op function type PanwClient interface { Op(req interface{}, vsys string, extras interface{}, ans interface{}) ([]byte, error) @@ -35,7 +39,7 @@ func GetPanwClient(config *Config) (PanwClient, error) { return &PanwTestClient{}, nil } - firewall := pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} + firewall := pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey, Port: config.Port}} err := firewall.Initialize() if err != nil { return nil, fmt.Errorf("error initializing firewall client: %w", err) diff --git a/x-pack/metricbeat/module/panw/config.go b/x-pack/metricbeat/module/panw/config.go index aface5a6397..bf1f859723a 100644 --- a/x-pack/metricbeat/module/panw/config.go +++ b/x-pack/metricbeat/module/panw/config.go @@ -16,6 +16,7 @@ const ( type Config struct { HostIp string `config:"host_ip"` + Port uint `config:"port"` ApiKey string `config:"apiKey"` DebugMode string `config:"apiDebugMode"` } diff --git a/x-pack/metricbeat/module/panw/fields.go b/x-pack/metricbeat/module/panw/fields.go index 42650ff9eb1..d8450a6f61f 100644 --- a/x-pack/metricbeat/module/panw/fields.go +++ b/x-pack/metricbeat/module/panw/fields.go @@ -19,5 +19,5 @@ func init() { // AssetPanw returns asset data. // This is the base64 encoded zlib format compressed contents of module/panw. func AssetPanw() string { - return "eJzMmstu4zYUhvd5ioNZtUBGmCT1wl4UCOaSDlAXg85MF90ItHRks5FIghc7ztMXFCVHlqlLZHpa7ZJI//dRPD4kjbyFR9wvQBDG1RWApjrHBbwpf35zBSAxR6JwASvU5AogRZVIKjTlbAG/XgGAexYKnpocrwAyinmqFuWf3gIjBb7E20vvBS5gLbkR1W88mccxzSjKNMqMJKgOf/Jl2qvtXl9enru86W2Vpg4+kUKU425ezucR9zsu09bfeuj2+ugCHfRk9JIbTdn6EkM/jf4fjVvtlcbiEsM+Se4btRGaFhilZK+8I7fls0b5upF/L0OBMjjJbXE33MiA4N9sHCS8EJwh08CzCtTnUFBmNAa0WLpAn0d1h19HoYwTbpgOp/KHKVYoS75C6Z+KnJM0JluUZI3RTeGFZzknba0B9O+cpFDF2lK4Afeihx1mF3OYgW+y/S/ichY3/RqaqEcVaa5JHq4Qvtk4YIdyKCE9eGkYO+6dZwq8VGIVPaigckRxIYc6e1hCcyGw3fnDOLjoQYVnXqyof10608Al9wgkwkS2cYT6JLz/8h2Msh+D1b7sSCAkT1Cpjo+C5Z8sZ+EMXPQIB0YT/wSca3BAw47qDRAQXFFNtwgWCVuSG3/DtFY07diuTLSyedC5WlrijlD/4jSRaPP6iRsakrchMt0RiW5XLI3QQ3UX047leKKB4pkebaCxYwmYCreB3e+7wILLfc/KMwHr1h2X3AfNJAar5U8ScQTSqI6+PgH5XWE6ArkyWWY3eSTZBBvtsoy23TSFjEtwDAWEpXAKOhw/dkRcYqZtLihBkh5s8LkeAw0+22OgZEtoTlbh2vR9HTiEz2mCTGGUIdFGTj7VfnKP13FpL6vxpJen8al3uB9efmgdmn00hZJ2VO+IgX0tn25siKvYXiRVynRUUUp0+yUf8T6Xj5a3jRgbPgkqO46kQ6SP7tnXofyDWnGeI2lPpoeWjgARozdxwtPJtXhv9AZsQA8sozm6hTuyv5iK8vSZQzCcBHvgij4HhH+lz3gNlCW5Se2hxTCq1TXg9Rrm0ewhqu8bsursgZOs7gtumC4XHp9ctI7gl+jdwwiv/jY5Se4DVY+uPcIhvctyFs0eRry6WKBMsGM7OEnyiwu07ecFBSez5NEpX33IyWzUt5tWwds734MGYZHKuY5d8wx3MP22weY3FBt82a9bXqfM0Loz6YVYmcYttVHWaodND5IT6T+ojmikpwaflSVKBMKgjAaliTZqjIoUfpHJ86IEYtogA2Xw55dlp0BBWRxcoqCMFqZ4lYx9hQXJQ1Ts15zrukC7l6Aa+GN2QzXtrNq7L6trzJDWElHFCeaKGv/2ZHBT+8GFwHsXMgJbTXussRDTmMuqcGwCSrelHcElT+dyXcJIruA7lIOFOmZzO6pQHe7HlKljnVWkn1lKE6JRAc2qfkgVkETTrX875phbnuuJlfreSGmX579shH8T4xh1gZ7Bqiu0jACJCZdpxzagYlbFeQ6zqs5jprvRSy7PP5Or8rSnu7xW2XjJCUpNs3L+3SlMxsqs/sFExxuiNqGVjsIn+j3i/jJudfBrvdJVbOHhfKrACR74JGLPOfYMl/IYS8ouZIOvIeOyIHoBdzfv7m7nt3ez+Wz+909LIuF2Drd3i9l8MZvD7bu7G3hYfvv5VfoSt4H1G6ETXqf7KiRmPKjQIXWCkT2qBJWxgRM8wn4JUAVOmaFy5x52etxhoMPl6Imrtt1WNJfaYP95chz7H/6zzb8BAAD//xyMzHA=" + return "eJzMnV9v3DiSwN/zKQq+h3UAxxM7yAIxcAf0xjNjA06mETuzh3sR2FKpxbNE6kiqnZ5Pf+Af/W2ppZap7Gax2LXdXfVjsVgslkjqHTzj/gZywl7eACiqUryBM/3j2RsAgSkSiTewQUXeAEQoQ0FzRTm7gf96AwDmm5DxqEjxDUBMMY3kjfnLO2Akw0q2/qf2Od7AVvAid7/pkdiW0pREmUIRkxBl9ac+mfpfl7z816vP/uuV3kVpNSzZSxqS9FL/2PpESfWM+xcuos7fjjDof2sntgaCAwUHCLSrxC/A/e1x9VrbogBaGpyzIkNBQ9iRtECgDCQvRIjw318eLkAqQdnW/U0iU6A4YEqkoqFEIsLk7c2BKoD3NwBnv6oEBUNVazy76Pnslf7sarsVuCUKofrW+erXtyNfvdZfvaPbBFY7QlOyoSlVezi/W41984P+5p8Pq68jn/uoP/fAeb4h4fPIZ/+uP/tUMIbpWJPf38DZ4+27fx7Rf+AOGQkX8IYvq89AokiglMfVyxxx2fFwqOEAIiryFH/4o7g18iDkLKbbQhD9uQvAy+3lBZzFRZqeARdwlpA0PhsxjyJq2dFqNNxAkf8S8Rc24is8WhZGKygNRQrFGW6PE2ljBksZSQu39rmwXvSLdZRf3O9ch169f//+F/3ZX4p8pDsJBhlmGxT+aH/jAkgV5uqJ8QJUgkCEIHvgMVi1/RNnDZry7QKz5IOVOmWSLAF8zpGH6gemyFK5Itte7VrA9qDvRrSb2UCRLRApeUiJwgheqEpAJVTWTEeBdnIvPRJRoQqSgtxLhZmeeV8SGnaBYIMpZ1sJR8n+4mwBR9FSq+FFmaQR2ojJC2V+OMoUv3h0nnsW0ZAolEBjM6JqA1EJhcQIYi70f1+IiCjrj1eVW+f93dj99UQ73a9hZSdZ61Ky2OgUJyPyuTTf1dXV5fX19eWHDx8ur97/cv3pKJ+esr3Z7rs2juIgFRcIJKL6c8RGVBpqeJchjASjaM8Cr2Bwu2cko2Gtv7TWFhkKM0Q3e7i9+7wetdbf/Xv//Xr39xINmsPvP+BuBfeV/9n1DvQP0IRcIiObdCC52nCeImGnAd6toE9mQ6XfBOFu1UoIzkio6A7f2f+xAcH9KidS6t8NcYmCMcq2gdwzj9luHRt0YJD7MBGc0b9Mume8vJB66tV/vFtBTqiomqJB7KcxOrs4Y1y96/yq/pGy7aSGBd47vBX8nKp2Vgs1pv2ZyjEfSXlI0oCymF/uUEjKu1AWWE8+J7tLm03rgD4d/TSe08i7lc0dSxcwmiDCHQ27Lm19ecyJu6hB5BrqyX63td0go2lKJYacRZUPh4UQeql+aKd+yGybqcDTjHe3cvYzfZoRRraYaZj7/hDdJskFYpZrSy8xNl4SVAkKY6OYCnwhaarHQemMdhasGdI9KPKMwHcogNjgYf0ACkaVNj9hxn1QFfkUQ/+bRt1mD6RExVxkgRadelyrObkGOe0bapNHk9+54bEK/7oj20GyMm3IszxFdcKQN3HebwXvaZ+bGFUntlVWe4g+ATQhVwHNBxO2U0d+I8c1xryqQS9q0gSJUBskCgiLmvFhHn9GQr8ZZzt+6VaMVcgOoXIu1BLJi1399a9rNKkSJI5pWHlthPab0buEXE1xXQ2/IeFzkft0jKcEwUptLCUMtE24rkYW14OMP6HzHffpPuAQ/brCIJ9WY7sdzuoxdWKXb4nCF7L30ue3GJMiVeBkVr3teFudPrguamFe+3TJriGvG545kWZx57s+2euu/y0jz/UUN9wUNI0C4TPj0GFnvfr67o9HkDxWL0RgucaolkictZPBCaSFSINjy6HZrCWbS42+f3uAmKYKzQO4iCiyIXLSWCF5/lMISZ6nupf1r07ho1z552uPnnv+VCNNX1iSnXewPrsxRXdUFLJCnICmEoFkcbtZLSdYbJezIEwpMv9of7at9uf6K1hNcE51EiwVSVOM3k6g3OZLQXYpf0/5hqRrwRWGquStws8Qao4oLGnIGQtsRcof4x87FMQ9IWtVurQ2DPXXJJyfFfkZZEiYBP3h5t80O8/RVh1IOmjyuh2eSzSfXUWjAdGu2WjNdRg/dwte1xy9VJdmZ4MiLNrszRrUrD8YV5AQFqU6xrpJbGrrfFd17viL+VbdnoRI2CCaOs/kuk5N6bOs86VZyKly+D7jj3MtW+ShcVXBaVU5y7n+RNhFSjbNilMfVpnKr2z5Zj1SvmmYdqHqzZdm0aY91qb0N+WCqv6FxazqcSnR7Uua54b+yx+dYdFe5DT6eRrbAguMVjGjabZpRP5LA7ov0ex2aK9nx1djvWRLrMl6+SaszJqAvteuTaYpS9c2y9JWmrRw7aQ8Cbm69J32rDWT7rQ6lXEpULVOHdoH1A+YC5oR0R/HZs1ajzmGNKb1noUOLZXQp/M4ZUOnP1ve1n+unjLVnGYj6YWzaV3htcaebuFr7y7Q8swGsHbSHl3H4X5G91+/svuvl+n+Y3YcUnjUS13E/okdXsXuwxDQWiY0lhinN+cnG79q04Q+SCl7DjLOqOKCsq3/TSetFFxrg1rblN0GHb6Y0LQQGISc2Q1JHleTpUhQCVGgBN1uUUggB9gOon7EyvbD1cxOA8zpCc8bNL+SrN6m0GHtntaYALesDwxCzvAGy/sv8QmntFyEezB7tShY0DsatfoFuH2H7cdWZepE9pJb8EK193V6O8Z0KPrYGabNNrdzhN/ufUrsfuzuNh83OZjf/eP3tf15uHs13c7uLA50u3zucTfVbrdr2cq2+13LfcsNQCobG62Pm/GwLV7t2LaZ3V1tfi43Vit+nM+2NBjYCn/q+q7CcQYc2AOvtQvMuMKAyIBIX2VIbR0rF1aF4oxnvJDwaLegn68e3wIrzAmFsfKBBvQdJ55cd0mUsmc596tUZJNSmWBUJnVmw6f7NJVQ5Kbu657/jXD7rvA+0cwesHPb9SRlIR5UdgsJL0SCRDXsdURKbbyg+yHPG+UIlJq07SSq6jl+6aRHEZer8HYjCWVQlfx5pAddDHu73ZfVgShNTcGfMqp01AHSWsPycXfOilTRIOF5oFR/dXWmUygODxr+/Onp4a2rampTG4XvEp43vV5eHg9HfZWX1+0DqEubevDkXKhJo98+gfOO82CeVx4QVRsStKnqjj0SPOMUQ8WFezb4k1yVWH+ESj30qG/FIpKZjDfGCI+Eo1mka9Q5rssdtCJoKQL8ESaEbdEySyikWczp/IyR1LTrnP7j9/Vb8zwWSaT9An80/4z6z4ONqw7EuRYGpN9RXtkPJqcfmM5KhM7jojLSDVu+O/Ao23re8XmLMWXu1IJyuz8FpgZFJjTXGewLIjPO1ZgGGx1wdgFn96z1Mxdw9p1JV3yK+he0ulFuEAUCldgHptd3xFvcKxP9HUnhvJ4V31aNagRnTUAHTh9pUp4jCyJMB3avzdhir2XBBmMuzLn3SPs9YfBHjgwylJJssUU9iEajFIOEp/3J4Uy7RSmClglKzx4d6xlm02cGumlHEuuZ0K1oh51ZYEx/BCnNaH9UnEedkR80K7JG/mgVleMzJAw2mjxEutMjUPCsfrB3/h7+ExgHQzVsbm0VbZSFUjZbHGiGdJNWvBBqcyMCz4g5Se3mA+MmF8Bwy5U9UNoasKONCOxzYk9t+Ya5QIlMyXrvfbpvPouuXcrUQdw6aBCzauriIYEot4TUZj+wsN2gols2w9aVNL/G1m2pQbvP+8csm8ltUOSRnhepz4VdPfS0Ib+vb1dPv9ZWrEbeZm88xCXObhyewMwLX3FDjUKbS0mqUGH3sjnwSSm93AaKK7NTzJehtTiNS9K0x7itsDaBy58x+8HKW13G03kiVdnDZLtUhK0XxVofWH3VlKtXxida0mCjENxzncvgaY80sivCE+lcpSFOSR6EvGCqP/893a7tM6+Nmg3N3O+ahZSESDjTEDlG5uiYEoRJUxBvRFJXPYn4iy29HMnIsC7F+G3X1wktkUUYopRxoee3Vkucn7crRcP76UxuKeIAmc6Ay6713pI/vv0G538UasMLFsE3sz78rdz7/Ra0dnp6CGH4QyU8DySmsb9F1T8bhyhdnD04QllIBKq03vLYpGYxdQydJLnFZB14xqaWsiUqoSLKiRjYSzarPU9a5jsjtEGJRJlnPscfVDXZDhqwwKHVsoawQZ3Zm4JHn32rrjl0ma6ly5bYK0bedNk9PDo5kHzsyUmR60F9GRGf16h8N0L1HHMgt6M34YXwqPhOi4OQZzlnZvdy7BQdY8goK7qB9VUUX6zAPg73iX4cicJGbu/hToseukmERAHZoSBbvLzKejXHKSddptGKIYnAidV+cAXWyuMMHxdj+Ah9Pd1viOUoro5jKCKf5aXJQ73moI10RGs4orvvSY0PHyxPgI3plylivgRAKXicQHGdlfkHsHJH9f/Fsw31le3X6q3YI9rDvLjUkcKX639ef4fCpOibvQlBkAseDt9qpPUfTF7+CNylXuMMrHs3gi+CSrV9Rk8g5zpP3iFolfYp1CAVjVKvVKakOTg3ao0vZKAaOVOjqdkd1ZhQn/oSIiJzCsyUuESRqzG/C+jA5DuToDqHNoVA4UDMn6tcCxy2d4YZF/sjU80MtXausZKPKY0FevPl3wTiBJU6d/el0lzfNq5yU8SxTulImHhr7Rcjun70anXYh7KHiqrFxgvJl+hpLRdkPnSPhFHrva+nKPXe21OUEnslsr8wvSoFjqlPaYhM4qVbRffqn3eFqluWOwWROye3inaEhRjBkz2+vBa4Qzb4vLbEG9usrfDHiRbqOSVRokKfMbpEEgUdGBTztlUaeY1s2yk6CkGlLAbcNTo81DtmEaKwaQdTwO3R0IXAHzkVA6tgDxRO/MCVqS2GZXdHWxwqoU9ZF4gUKglCrwdSV4VKuCjvBNSyQXF7yZk5XS3Kg/ZN3l7ImKZo0xbPu5p/qwTDgeAe5ZL+NT3ixVxkRN3AZn9Ycpk25dC/qn2kNUT5mTHWk+aFV7CuMl4wt0OquvKkhh3DPH0meQXrLZXPdm6BSu8h9ATLBjmKcGhfV38lrcTu/+boXirzJe0NDeMedHEPrOkdn5frN4aM7fmcd5cSFQZhlzLlKrCTxAnGOulxs+69agGk9Q3CLHKESsNEh5NzTPozBM1BUiL6V/7zYr+p0wsEwsCI7tzGcQxF5P0gs/vF3JHf0AyUwbf1l0GAjLLAO0RGmdkOdAqMNmFG0mU89jHlqnRZ85DiKMKy2eO4fs/+uTI+OaXZW4EogxBTSQe29s9YW9xasfDZip0A4twnUJj1nw2Zs5x1LqllorBrjQkkdl+bXxK3V24aSc5fUIwOinlLiEmDwgL8q4aE1e47YDeTdRuxqXTX/x6h2PF0YKvDnLqZOxbypxban6ZZreVg8Kq9HA1GKAgMuYiGXtBjKdxA8EvhRkKbwv6tlyVEoWhs+s6uZT2OBiuv44oTKQJZbP4XQxUkRCa+kVrCZ/I9434ZtlLwqVzRxvN+eidwBgf+yIOeusMrWMyCv7o8ES+qxceHq/cfrj9df/j46eOn/zn/QgRcf4LrDzcfP918/ATX7z9cwe9fnt6ehC9w5xm/IXSGOW2hK2DcK1AldQaRXo55hdECZ3D4rZ04gXN6yPPJzUrkEEvrG2+6dLu8OX1725zUFntsZ9LWXOyY24sdL91mw8uIZ2Rg3/C8Az9GXv9lkk7nCXRUBmY/9EJJUedo7aGq43SFROHV2787gaX5TjeYu20n8I4GaysZilczCtxSzoKYi2MHFmZBfjOizYO81vtZTqCz7w4NLKTHVYh9JakVO992Ic9yvxcefHYS7YUC5UHK08GGT6DOw7IXz1Jmk4pXGW2Xs4VeZPHn+qutSc+2W8KlGrp3Yd5dS1wquL+db61FLt9eNW7aLi+Tfp3hygtAPF0PW76p8PASzNeg7frf2TYfrvG6tvlzRLFJaejLcGsjzYvdKjBPZqvQfFhNmdciLxRHrPBXjghnvvqwrHdLNs7h+jGqu9Pckyu6OcOHK6Z8S1kweAz39Af4D1qgO5n6eqigUP0vkHoVGGXw/enzK/hojB5PLj84ca/JNP+vQKkCYzifWaYRa17OyfykKCXpFtUCSbHF3aLqeWuhN3QpU/MuBRsj/OM/Pj7YVyhYBa+Dd2/1WfD6uvbSt+/NRMfJ3IVKweFRk/kjqqzGs/ZBltKk9enC18LnAneUF9Ir/doJXQ7fHldewPJ2q004xfwt9snMixjcUueTzD6OTXOJYWAzHa8vXa8XO/driaFLpsYZlhv7p3FsX/xR/O7eVjYL5OmR+krFnuybSOAR3RVR9/bKMv3/1pfwZN7/3rjFQydt5+8vzX/KV7iwfSOV678v5QDf3sfisVdRvXDx7O55qc6mPj1SuF9fQMnKOLjbiEJg7itUQmRuP4r6bzvrYefK4+MEPRZ5yNPGJZX2mEzZgPOmpXP36al2HnpN24ywzkUVEruoh5hcDFyd00EUi3nyN5Q5ZxEaT56G8tO80o6uR5rRlJjbQwbGxBFSrz6oiUrPmhuThE9nM0CN2/9Og1lqhM6C8fteHxORZXWdf42j1Vy6e9n+pgqW/m0cLfL4BP6WxjHFd3eYphlh7obbWQZDny9d/pWFYm+39ZB0ywVVSTYPy++GhTsik9cS6XW8r/Fm9ty31/EW5hHDwrwBaeVivjbl+ePqbeMqnXHU540vUBfmdzwtMrR3tJnA+rgCgc+4p2z75v8DAAD//+EsS/8=" } diff --git a/x-pack/metricbeat/module/panw/interfaces/_meta/data.json b/x-pack/metricbeat/module/panw/interfaces/_meta/data.json index 4efd71bc73c..50315d045c7 100644 --- a/x-pack/metricbeat/module/panw/interfaces/_meta/data.json +++ b/x-pack/metricbeat/module/panw/interfaces/_meta/data.json @@ -6,11 +6,11 @@ }, "metricset":{ "host":"localhost", - "module":"panos", + "module":"panw", "name":"interfaces", "rtt":44269 }, - "panos":{ + "panw":{ "interfaces":{ "example": "interfaces" } diff --git a/x-pack/metricbeat/module/panw/interfaces/_meta/docs.asciidoc b/x-pack/metricbeat/module/panw/interfaces/_meta/docs.asciidoc index fba7410ae86..affd907c295 100644 --- a/x-pack/metricbeat/module/panw/interfaces/_meta/docs.asciidoc +++ b/x-pack/metricbeat/module/panw/interfaces/_meta/docs.asciidoc @@ -1 +1 @@ -This is the interfaces metricset of the module panos. +This is the interfaces metricset of the module panw. diff --git a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml index 79963bfd5f5..0f0bd265a94 100644 --- a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml @@ -15,7 +15,7 @@ - name: physical.type type: keyword description: > - Physical interface type: + Physical interface type (numeric value in source XML, string value sent to elasticsearch): 0: "Ethernet interface", 1: "Aggregate Ethernet (AE) interface", 2: "High Availability (HA) interface", @@ -50,7 +50,7 @@ - name: physical.ae_member type: keyword description: > - For aggregate interfaces, the member interfaces + For aggregate interfaces, the array of member interfaces - name: logical.name type: keyword description: > @@ -66,7 +66,7 @@ - name: logical.vsys type: integer description: > - Logical virtual system + Virtual system to which this interface belongs - name: logical.zone type: keyword description: > @@ -199,7 +199,7 @@ - name: ha.local_info.iot_version type: keyword description: > - HA local info IoT version + HA local info IoT database version - name: ha.local_info.av_version type: keyword description: > diff --git a/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go index 1ccc4514d56..42f13ecd3f6 100644 --- a/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go +++ b/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go @@ -16,14 +16,14 @@ import ( const haInterfaceQuery = "" -var logger *logp.Logger +var haLogger *logp.Logger func getHAInterfaceEvents(m *MetricSet) ([]mb.Event, error) { // Set logger so all the parse functions have access - logger = m.logger + haLogger = m.logger var response HAResponse - output, err := m.client.Op(haInterfaceQuery, vsys, nil, nil) + output, err := m.client.Op(haInterfaceQuery, panw.Vsys, nil, nil) if err != nil { m.logger.Error("Error: %s", err) return nil, err @@ -59,15 +59,15 @@ func makeGroupEvent(m *MetricSet, input HAResult) *mb.Event { timestamp := time.Now() linkMonitoringEnabled, err := panw.StringToBool(group.LinkMonitoring.Enabled) if err != nil { - logger.Warn("Error converting LinkMonitoring.Enabled to boolean: %s", err) + haLogger.Warn("Error converting LinkMonitoring.Enabled to boolean: %s", err) } enabled, err := panw.StringToBool(input.Enabled) if err != nil { - logger.Warn("Error converting Enabled to boolean: %s", err) + haLogger.Warn("Error converting Enabled to boolean: %s", err) } syncEnabled, err := panw.StringToBool(group.RunningSyncEnabled) if err != nil { - logger.Warn("Error converting RunningSyncEnabled to boolean: %s", err) + haLogger.Warn("Error converting RunningSyncEnabled to boolean: %s", err) } event := mb.Event{ @@ -151,11 +151,11 @@ func makeLinkMonitoringEvents(m *MetricSet, links HALinkMonitoring) []mb.Event { for _, interface_entry := range group.Interface { linkEnabled, err := panw.StringToBool(links.Enabled) if err != nil { - logger.Warn("Error converting links.Enabled to boolean: %s", err) + haLogger.Warn("Error converting links.Enabled to boolean: %s", err) } groupEnabled, err := panw.StringToBool(group.Enabled) if err != nil { - logger.Warn("Error converting group.Enabled to boolean: %s", err) + haLogger.Warn("Error converting group.Enabled to boolean: %s", err) } event = mb.Event{ diff --git a/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go b/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go index 69aaaa54398..7edd1e3b4a1 100644 --- a/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go +++ b/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go @@ -9,6 +9,7 @@ import ( "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/mapstr" ) @@ -29,7 +30,7 @@ func getIFNetInterfaceEvents(m *MetricSet) ([]mb.Event, error) { var response InterfaceResponse - output, err := m.client.Op(IFNetInterfaceQuery, vsys, nil, nil) + output, err := m.client.Op(IFNetInterfaceQuery, panw.Vsys, nil, nil) if err != nil { m.logger.Error("Error: %s", err) return nil, err diff --git a/x-pack/metricbeat/module/panw/interfaces/interfaces.go b/x-pack/metricbeat/module/panw/interfaces/interfaces.go index bfaa491c116..e3fbceaa00b 100644 --- a/x-pack/metricbeat/module/panw/interfaces/interfaces.go +++ b/x-pack/metricbeat/module/panw/interfaces/interfaces.go @@ -16,7 +16,6 @@ import ( const ( metricsetName = "interfaces" - vsys = "" ) // MetricSet holds any configuration or state information. It must implement diff --git a/x-pack/metricbeat/module/panw/routing/_meta/data.json b/x-pack/metricbeat/module/panw/routing/_meta/data.json index 8bb0746b1e8..133eaa06d18 100644 --- a/x-pack/metricbeat/module/panw/routing/_meta/data.json +++ b/x-pack/metricbeat/module/panw/routing/_meta/data.json @@ -6,11 +6,11 @@ }, "metricset":{ "host":"localhost", - "module":"panos", + "module":"panw", "name":"routing", "rtt":44269 }, - "panos":{ + "panw":{ "routing":{ "example": "routing" } diff --git a/x-pack/metricbeat/module/panw/routing/_meta/docs.asciidoc b/x-pack/metricbeat/module/panw/routing/_meta/docs.asciidoc index bee51fd8b44..a0007378f3a 100644 --- a/x-pack/metricbeat/module/panw/routing/_meta/docs.asciidoc +++ b/x-pack/metricbeat/module/panw/routing/_meta/docs.asciidoc @@ -1 +1 @@ -This is the routing metricset of the module panos. +This is the routing metricset of the module panw. diff --git a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml index 20b53dc6895..d594612c9c7 100644 --- a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml @@ -7,144 +7,144 @@ - name: bgp.peer_name type: keyword description: > - BGP peer name + The name of the current peer in the BGP peer group - name: bgp.virtual_router type: keyword description: > - BGP virtual router + The virtual router with which the BGP peer is associated - name: bgp.peer_group type: keyword description: > - BGP peer group + The name of the BGP peer group this peer belongs to - name: bgp.peer_router_id - type: keyword + type: ip description: > BGP peer router ID - name: bgp.remote_as_asn - type: keyword + type: long description: > - BGP remote AS ASN + The remote Autonomous System (AS) number of the peer - name: bgp.status type: keyword description: > - BGP status + The BGP session status, e.g., "Established" means the session is up and running - name: bgp.status_duration type: long description: > - BGP status duration + Time in seconds since the current status was set - name: bgp.password_set type: boolean description: > - BGP password set + Indicates whether a password is set for the BGP peer - name: bgp.passive type: boolean description: > - BGP passive + Indicates if the BGP peer is in passive mode: if yes then router will not initiate a connection to the peer - name: bgp.multi_hop_ttl type: long description: > - BGP multi-hop TTL + Time to Live (TTL) value for multi-hop BGP sessions. - name: bgp.peer_address - type: ip + type: keyword description: > - BGP peer address + IP address and port of the peer - name: bgp.local_address - type: ip + type: keyword description: > - BGP local address + Local address and port used for BGP connection - name: bgp.reflector_client - type: boolean + type: keyword description: > - BGP reflector client + Indicates if the BGP peer is a route reflector client - name: bgp.same_confederation type: boolean description: > - BGP same confederation + Peers in the same confederation exchange routes using internal BGP (iBGP) instead of external BGP (eBGP) - name: bgp.aggregate_confed_as type: boolean description: > - BGP aggregate confederation AS + Indicates that Autonomous System (AS) aggregation is enabled for the confederation - name: bgp.peering_type type: keyword description: > - BGP peering type + Defines the type of relationship between peers, e.g., "External BGP", "Internal BGP", or "Unspecified" - name: bgp.connect_retry_interval type: long description: > - BGP connect retry interval + The interval (in seconds) between connection retries - name: bgp.open_delay type: long description: > - BGP open delay + Delay before sending an Open message (in seconds) - name: bgp.idle_hold type: long description: > - BGP idle hold + The idle hold time (in seconds) before retrying a connection after failure - name: bgp.prefix_limit type: long description: > - BGP prefix limit + The maximum number of prefixes that can be received from the peer (0 = no limit) - name: bgp.holdtime type: long description: > - BGP holdtime + Time in seconds that the BGP peer will wait for a keepalive message, negotiated between peers - name: bgp.holdtime_config type: long description: > - BGP holdtime config + Represents the locally configured hold time on this peer - name: bgp.keepalive type: long description: > - BGP keepalive + The interval (in seconds) at which BGP keepalive messages are sent, negotiated between peers - name: bgp.keepalive_config type: long description: > - BGP keepalive config + The keepalive configured on this peer - name: bgp.msg_update_in type: long description: > - BGP message updates in + The number of BGP UPDATE messages received by the router from this peer - name: bgp.msg_update_out type: long description: > - BGP message updates out + the number of BGP UPDATE messages sent from the local router to the peer - name: bgp.msg_total_in type: long description: > - BGP total messages in + Total of all messages received from the peer - name: bgp.msg_total_out type: long description: > - BGP total messages out + Total of all messages sent to the peer - name: bgp.last_update_age type: long description: > - BGP last update age + Time in seconds since the last update message was received from the peer - name: bgp.last_error type: keyword description: > - BGP last error + The last BGP error message received from the peer - name: bgp.status_flap_counts type: long description: > - BGP status flap counts + Indicates the number of times the BGP session has "flapped" or transitioned between up and down states - name: bgp.established_counts type: long description: > - BGP established counts + Number of times the BGP session has successfully transitioned to the "Established" state - name: bgp.orf_entry_received type: long description: > - BGP ORF entry received + Number of ORF (Outbound Route Filtering) entries received from the peer - name: bgp.nexthop_self type: boolean description: > - BGP next-hop self + Whether the router is configured to use itself as the next-hop for routes sent to this peer - name: bgp.nexthop_thirdparty type: boolean description: > - BGP next-hop third-party + Third-party next-hop feature is enabled - name: bgp.nexthop_peer type: boolean description: > - BGP next-hop peer \ No newline at end of file + Indicates whether the peer is being used as the next-hop for the routes received from this peer \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/routing/bgp_peers.go b/x-pack/metricbeat/module/panw/routing/bgp_peers.go index 5d5c48862c9..674bb96a72f 100644 --- a/x-pack/metricbeat/module/panw/routing/bgp_peers.go +++ b/x-pack/metricbeat/module/panw/routing/bgp_peers.go @@ -9,13 +9,18 @@ import ( "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" + "github.com/elastic/elastic-agent-libs/logp" "github.com/elastic/elastic-agent-libs/mapstr" ) const bgpPeersQuery = "" -func getBGPEvents(m *MetricSet) ([]mb.Event, error) { +var bgpLogger *logp.Logger +func getBGPEvents(m *MetricSet) ([]mb.Event, error) { + // Set logger so all the sub functions have access + bgpLogger = m.logger var response BGPResponse // Initialize the client @@ -24,7 +29,7 @@ func getBGPEvents(m *MetricSet) ([]mb.Event, error) { // return err // } - output, err := m.client.Op(bgpPeersQuery, vsys, nil, nil) + output, err := m.client.Op(bgpPeersQuery, panw.Vsys, nil, nil) if err != nil { m.logger.Error("Error calling API: %s", err) return nil, err @@ -41,55 +46,87 @@ func getBGPEvents(m *MetricSet) ([]mb.Event, error) { return events, nil } +// Convert yes/no strings to booleans. Convert any errors to false and log a warning +func convertEntryBooleanFields(entry BGPEntry) map[string]bool { + + fields := []struct { + name string + value string + }{ + {"bgp.password_set", entry.PasswordSet}, + {"bgp.passive", entry.Passive}, + {"bgp.same_confederation", entry.SameConfederation}, + {"bgp.aggregate_confed_as", entry.AggregateConfedAS}, + {"bgp.nexthop_self", entry.NexthopSelf}, + {"bgp.nexthop_thirdparty", entry.NexthopThirdparty}, + {"bgp.nexthop_peer", entry.NexthopPeer}, + } + + result := make(map[string]bool) + for _, field := range fields { + boolValue, err := panw.StringToBool(field.value) + if err != nil { + bgpLogger.Warnf("Error converting %s: %v", field.name, err) + boolValue = false + } + result[field.name] = boolValue + } + + return result +} + func formatBGPEvents(m *MetricSet, entries []BGPEntry) []mb.Event { events := make([]mb.Event, 0, len(entries)) - currentTime := time.Now() + timestamp := time.Now() for _, entry := range entries { - event := mb.Event{MetricSetFields: mapstr.M{ - "bgp.peer_name": entry.Peer, - "bgp.virtual_router": entry.Vr, - "bgp.peer_group": entry.PeerGroup, - "bgp.peer_router_id": entry.PeerRouterID, - "bgp.remote_as_asn": entry.RemoteAS, - "bgp.status": entry.Status, - "bgp.status_duration": entry.StatusDuration, - "bgp.password_set": entry.PasswordSet, - "bgp.passive": entry.Passive, - "bgp.multi_hop_ttl": entry.MultiHopTTL, - "bgp.peer_address": entry.PeerAddress, - "bgp.local_address": entry.LocalAddress, - "bgp.reflector_client": entry.ReflectorClient, - "bgp.same_confederation": entry.SameConfederation, - "bgp.aggregate_confed_as": entry.AggregateConfedAS, - "bgp.peering_type": entry.PeeringType, - "bgp.connect_retry_interval": entry.ConnectRetryInterval, - "bgp.open_delay": entry.OpenDelay, - "bgp.idle_hold": entry.IdleHold, - "bgp.prefix_limit": entry.PrefixLimit, - "bgp.holdtime": entry.Holdtime, - "bgp.holdtime_config": entry.HoldtimeConfig, - "bgp.keepalive": entry.Keepalive, - "bgp.keepalive_config": entry.KeepaliveConfig, - "bgp.msg_update_in": entry.MsgUpdateIn, - "bgp.msg_update_out": entry.MsgUpdateOut, - "bgp.msg_total_in": entry.MsgTotalIn, - "bgp.msg_total_out": entry.MsgTotalOut, - "bgp.last_update_age": entry.LastUpdateAge, - "bgp.last_error": entry.LastError, - "bgp.status_flap_counts": entry.StatusFlapCounts, - "bgp.established_counts": entry.EstablishedCounts, - "bgp.orf_entry_received": entry.ORFEntryReceived, - "bgp.nexthop_self": entry.NexthopSelf, - "bgp.nexthop_thirdparty": entry.NexthopThirdparty, - "bgp.nexthop_peer": entry.NexthopPeer, - }, + booleanFields := convertEntryBooleanFields(entry) + + event := mb.Event{ + Timestamp: timestamp, + MetricSetFields: mapstr.M{ + "bgp.peer_name": entry.Peer, + "bgp.virtual_router": entry.Vr, + "bgp.peer_group": entry.PeerGroup, + "bgp.peer_router_id": entry.PeerRouterID, + "bgp.remote_as_asn": entry.RemoteAS, + "bgp.status": entry.Status, + "bgp.status_duration": entry.StatusDuration, + "bgp.password_set": booleanFields["bgp.password_set"], + "bgp.passive": booleanFields["bgp.passive"], + "bgp.multi_hop_ttl": entry.MultiHopTTL, + "bgp.peer_address": entry.PeerAddress, + "bgp.local_address": entry.LocalAddress, + "bgp.reflector_client": entry.ReflectorClient, + "bgp.same_confederation": booleanFields["bgp.same_confederation"], + "bgp.aggregate_confed_as": booleanFields["bgp.aggregate_confed_as"], + "bgp.peering_type": entry.PeeringType, + "bgp.connect_retry_interval": entry.ConnectRetryInterval, + "bgp.open_delay": entry.OpenDelay, + "bgp.idle_hold": entry.IdleHold, + "bgp.prefix_limit": entry.PrefixLimit, + "bgp.holdtime": entry.Holdtime, + "bgp.holdtime_config": entry.HoldtimeConfig, + "bgp.keepalive": entry.Keepalive, + "bgp.keepalive_config": entry.KeepaliveConfig, + "bgp.msg_update_in": entry.MsgUpdateIn, + "bgp.msg_update_out": entry.MsgUpdateOut, + "bgp.msg_total_in": entry.MsgTotalIn, + "bgp.msg_total_out": entry.MsgTotalOut, + "bgp.last_update_age": entry.LastUpdateAge, + "bgp.last_error": entry.LastError, + "bgp.status_flap_counts": entry.StatusFlapCounts, + "bgp.established_counts": entry.EstablishedCounts, + "bgp.orf_entry_received": entry.ORFEntryReceived, + "bgp.nexthop_self": booleanFields["bgp.nexthop_self"], + "bgp.nexthop_thirdparty": booleanFields["bgp.nexthop_thirdparty"], + "bgp.nexthop_peer": booleanFields["bgp.nexthop_peer"], + }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, "host.ip": m.config.HostIp, "observer.vendor": "Palo Alto", "observer.type": "firewall", - "@Timestamp": currentTime, }} events = append(events, event) diff --git a/x-pack/metricbeat/module/panw/routing/routing.go b/x-pack/metricbeat/module/panw/routing/routing.go index 1ba3904bc3f..79a9a685177 100644 --- a/x-pack/metricbeat/module/panw/routing/routing.go +++ b/x-pack/metricbeat/module/panw/routing/routing.go @@ -16,7 +16,6 @@ import ( const ( metricsetName = "routing" - vsys = "" ) // MetricSet holds any configuration or state information. It must implement diff --git a/x-pack/metricbeat/module/panw/system/_meta/data.json b/x-pack/metricbeat/module/panw/system/_meta/data.json index 931eba1a52a..c5cf6da116f 100644 --- a/x-pack/metricbeat/module/panw/system/_meta/data.json +++ b/x-pack/metricbeat/module/panw/system/_meta/data.json @@ -6,11 +6,11 @@ }, "metricset":{ "host":"localhost", - "module":"panos", + "module":"panw", "name":"system", "rtt":44269 }, - "panos":{ + "panw":{ "system":{ "example": "system" } diff --git a/x-pack/metricbeat/module/panw/system/_meta/docs.asciidoc b/x-pack/metricbeat/module/panw/system/_meta/docs.asciidoc index 59ea987088d..9fa06d4fca8 100644 --- a/x-pack/metricbeat/module/panw/system/_meta/docs.asciidoc +++ b/x-pack/metricbeat/module/panw/system/_meta/docs.asciidoc @@ -1 +1 @@ -This is the system metricset of the module panos. +This is the system metricset of the module panw. diff --git a/x-pack/metricbeat/module/panw/system/_meta/fields.yml b/x-pack/metricbeat/module/panw/system/_meta/fields.yml index 69dd48a622a..385c5ffe99a 100644 --- a/x-pack/metricbeat/module/panw/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/system/_meta/fields.yml @@ -119,11 +119,11 @@ - name: license.feature type: keyword description: > - Feature licensed + Feature licensed, e.g. Advanced Threat Prevention - name: license.description type: text description: > - Description field + Description of the licensed feature - name: license.serial type: keyword description: > @@ -131,37 +131,41 @@ - name: license.issued type: date description: > - Issued date field + Date the license was issued - name: license.expires - type: date + type: keyword description: > - Expires date field + Date the license expires, but this is a keyword because value might be "never" - name: license.expired type: boolean description: > - Expired field + Indicates if the license is expired - name: license.auth_code type: keyword description: > - Auth code field + Authorization code to activate or install the license - name: filesystem.name type: keyword description: > Filesystem name - name: filesystem.size - type: keyword + type: float + format: bytes description: > - Size, including units, e.g., 9.5G. + Total size of the filesystem - name: filesystem.used - type: keyword + type: float + format: bytes description: > - Amount used, including units, e.g., 4.0G + Amount used on the filesystem - name: filesystem.available - type: keyword + type: float + format: bytes description: > - Disk space available, including units, e.g., 5.5G + Disk space available on the filesystem - name: filesystem.use_percent - type: keyword + type: integer + format: percent description: > Percent of filesystem used - name: filesystem.mounted diff --git a/x-pack/metricbeat/module/panw/system/certificates.go b/x-pack/metricbeat/module/panw/system/certificates.go index 1993421fd43..1e82b3beedf 100644 --- a/x-pack/metricbeat/module/panw/system/certificates.go +++ b/x-pack/metricbeat/module/panw/system/certificates.go @@ -13,6 +13,7 @@ import ( "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/mapstr" ) @@ -22,7 +23,7 @@ func getCertificateEvents(m *MetricSet) ([]mb.Event, error) { var response CertificateResponse - output, err := m.client.Op(certificatesQuery, vsys, nil, nil) + output, err := m.client.Op(certificatesQuery, panw.Vsys, nil, nil) if err != nil { return nil, fmt.Errorf("failed to execute query: %w", err) } diff --git a/x-pack/metricbeat/module/panw/system/fans.go b/x-pack/metricbeat/module/panw/system/fans.go index 5e333c6e182..beec38f7c35 100644 --- a/x-pack/metricbeat/module/panw/system/fans.go +++ b/x-pack/metricbeat/module/panw/system/fans.go @@ -10,6 +10,7 @@ import ( "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/mapstr" ) @@ -19,7 +20,7 @@ func getFanEvents(m *MetricSet) ([]mb.Event, error) { var response FanResponse - output, err := m.client.Op(fansQuery, vsys, nil, nil) + output, err := m.client.Op(fansQuery, panw.Vsys, nil, nil) if err != nil { return nil, fmt.Errorf("error querying fan data: %w", err) } @@ -42,13 +43,17 @@ func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { for _, slot := range response.Result.Fan.Slots { for _, entry := range slot.Entries { + alarm, err := panw.StringToBool(entry.Alarm) + if err != nil { + m.logger.Warn("Failed to convert alarm value %s to boolean: %s. Defaulting to false.", entry.Alarm, err) + } m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) event := mb.Event{ Timestamp: timestamp, MetricSetFields: mapstr.M{ "fan.slot_number": entry.Slot, "fan.description": entry.Description, - "fan.alarm": entry.Alarm, + "fan.alarm": alarm, "fan.rpm": entry.RPMs, "fan.min_rpm": entry.Min, }, diff --git a/x-pack/metricbeat/module/panw/system/filesystem.go b/x-pack/metricbeat/module/panw/system/filesystem.go index 43a35c87913..16cc234c8dc 100644 --- a/x-pack/metricbeat/module/panw/system/filesystem.go +++ b/x-pack/metricbeat/module/panw/system/filesystem.go @@ -7,20 +7,32 @@ package system import ( "encoding/xml" "fmt" + "strconv" "strings" "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" + "github.com/elastic/elastic-agent-libs/logp" "github.com/elastic/elastic-agent-libs/mapstr" ) +const ( + KBytes = 1024 + MBytes = 1024 * KBytes + GBytes = 1024 * MBytes +) + const filesystemQuery = "" -func getFilesystemEvents(m *MetricSet) ([]mb.Event, error) { +var filesystemLogger *logp.Logger +func getFilesystemEvents(m *MetricSet) ([]mb.Event, error) { + // Set logger so all the parse functions have access + filesystemLogger = m.logger var response FilesystemResponse - output, err := m.client.Op(filesystemQuery, vsys, nil, nil) + output, err := m.client.Op(filesystemQuery, panw.Vsys, nil, nil) if err != nil { return nil, fmt.Errorf("error querying filesystem info: %w", err) } @@ -41,6 +53,8 @@ func getFilesystemEvents(m *MetricSet) ([]mb.Event, error) { } func getFilesystems(input string) []Filesystem { + + filesystemLogger.Debugf("getFilesystems input:\n %s", input) lines := strings.Split(input, "\n") filesystems := make([]Filesystem, 0) @@ -71,6 +85,45 @@ func getFilesystems(input string) []Filesystem { return filesystems } +func convertToBytes(field string, value string) float64 { + if len(value) == 0 { + filesystemLogger.Warn("convertToBytes called with empty value") + return -1 + } + + // value, for instance for "used", can be just "0", so just return that + if value == "0" { + return 0 + } + + //filesystemLogger.Warnf("convertToBytes field %s, value: %s.", field, value) + numstr := value[:len(value)-1] + units := strings.ToLower(value[len(value)-1:]) + result, err := strconv.ParseFloat(numstr, 32) + if err != nil { + filesystemLogger.Warnf("parseFloat failed to parse field %s, value: %s. Error: %v", field, value, err) + return -1 + } + + switch units { + case "k": + return result * KBytes + case "m": + return result * MBytes + case "g": + return result * GBytes + default: + // Handle values without units + if units == "" { + return result + } else { + filesystemLogger.Warnf("Unhandled units for field %s, value %s: %s", field, value, units) + return result + } + } + +} + func formatFilesystemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { if len(filesystems) == 0 { return nil @@ -78,16 +131,20 @@ func formatFilesystemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { events := make([]mb.Event, 0, len(filesystems)) timestamp := time.Now() - for _, filesystem := range filesystems { + used, err := strconv.ParseInt(filesystem.UsePerc[:len(filesystem.UsePerc)-1], 10, 64) + if err != nil { + filesystemLogger.Warnf("Failed to parse used percent: %v", err) + } + event := mb.Event{ Timestamp: timestamp, MetricSetFields: mapstr.M{ "filesystem.name": filesystem.Name, - "filesystem.size": filesystem.Size, - "filesystem.used": filesystem.Used, - "filesystem.available": filesystem.Avail, - "filesystem.use_percent": filesystem.UsePerc, + "filesystem.size": convertToBytes("filesystem.size", filesystem.Size), + "filesystem.used": convertToBytes("filesystem.used", filesystem.Used), + "filesystem.available": convertToBytes("filesystem.available", filesystem.Avail), + "filesystem.use_percent": used, "filesystem.mounted": filesystem.Mounted, }, RootFields: mapstr.M{ diff --git a/x-pack/metricbeat/module/panw/system/license.go b/x-pack/metricbeat/module/panw/system/license.go index 8130ccfac07..1e2741c9431 100644 --- a/x-pack/metricbeat/module/panw/system/license.go +++ b/x-pack/metricbeat/module/panw/system/license.go @@ -10,6 +10,7 @@ import ( "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/mapstr" ) @@ -19,7 +20,7 @@ func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { var response LicenseResponse - output, err := m.client.Op(licenseQuery, vsys, nil, nil) + output, err := m.client.Op(licenseQuery, panw.Vsys, nil, nil) if err != nil { return nil, fmt.Errorf("failed to execute query: %w", err) } @@ -46,15 +47,29 @@ func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { timestamp := time.Now() for _, license := range licenses { + expired, err := panw.StringToBool(license.Expired) + if err != nil { + m.logger.Warn("Failed to convert expired value %s to boolean: %s. Defaulting to false.", license.Expired, err) + } + + // + // March 20, 2024 + // May 27, 2025 + // + issued, err := time.Parse("January 2, 2006", license.Issued) + if err != nil { + m.logger.Warn("Failed to parse issued date %s: %s", license.Issued, err) + } + event := mb.Event{ Timestamp: timestamp, MetricSetFields: mapstr.M{ "license.feature": license.Feature, - "license.description": license.Description, // Fixed typo + "license.description": license.Description, "license.serial": license.Serial, - "license.issued": license.Issued, + "license.issued": issued.Format(time.RFC3339), "license.expires": license.Expires, - "license.expired": license.Expired, + "license.expired": expired, "license.auth_code": license.AuthCode, }, RootFields: mapstr.M{ diff --git a/x-pack/metricbeat/module/panw/system/power.go b/x-pack/metricbeat/module/panw/system/power.go index f9ead893383..b0b7370b48a 100644 --- a/x-pack/metricbeat/module/panw/system/power.go +++ b/x-pack/metricbeat/module/panw/system/power.go @@ -10,6 +10,7 @@ import ( "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/mapstr" ) @@ -20,7 +21,7 @@ func getPowerEvents(m *MetricSet) ([]mb.Event, error) { var response PowerResponse - output, err := m.client.Op(powerQuery, vsys, nil, nil) + output, err := m.client.Op(powerQuery, panw.Vsys, nil, nil) if err != nil { return nil, fmt.Errorf("failed to execute operation: %w", err) } diff --git a/x-pack/metricbeat/module/panw/system/resources.go b/x-pack/metricbeat/module/panw/system/resources.go index 8feed62155f..6c889d3fa2c 100644 --- a/x-pack/metricbeat/module/panw/system/resources.go +++ b/x-pack/metricbeat/module/panw/system/resources.go @@ -13,20 +13,21 @@ import ( "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/logp" "github.com/elastic/elastic-agent-libs/mapstr" ) const resourceQuery = "" -var logger *logp.Logger +var resourcesLogger *logp.Logger func getResourceEvents(m *MetricSet) ([]mb.Event, error) { // Set logger so all the parse functions have access - logger = m.logger + resourcesLogger = m.logger var response ResourceResponse - output, err := m.client.Op(resourceQuery, vsys, nil, &response) + output, err := m.client.Op(resourceQuery, panw.Vsys, nil, &response) if err != nil { return nil, fmt.Errorf("failed to execute operation: %w", err) } @@ -190,7 +191,7 @@ func parseUptime(line string) Uptime { } if matches == nil { - logger.Errorf("Failed to parse uptime: %s", line) + resourcesLogger.Errorf("Failed to parse uptime: %s", line) return Uptime{} } @@ -216,7 +217,7 @@ func parseTaskInfo(line string) TaskInfo { re := regexp.MustCompile(`Tasks:\s*(\d+)\s*total,\s*(\d+)\s*running,\s*(\d+)\s*sleeping,\s*(\d+)\s*stopped,\s*(\d+)\s*zombie`) matches := re.FindStringSubmatch(line) if matches == nil { - logger.Errorf("Failed to parse task info: %s", line) + resourcesLogger.Errorf("Failed to parse task info: %s", line) return TaskInfo{} } @@ -237,10 +238,10 @@ func parseTaskInfo(line string) TaskInfo { func parseCPUInfo(line string) CPUInfo { //%Cpu(s): 73.0 us, 4.6 sy, 0.0 ni, 21.7 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st - re := regexp.MustCompile(`(\d+\.\d+) us, (\d+\.\d+) sy, (\d+\.\d+) ni, (\d+\.\d+) id, (\d+\.\d+) wa, (\d+\.\d+) hi, (\d+\.\d+) si, (\d+\.\d+) st`) + re := regexp.MustCompile(`(\d+\.\d+)\s+us,\s+(\d+\.\d+)\s+sy,\s+(\d+\.\d+)\s+ni,\s+(\d+\.\d+)\s+id,\s+(\d+\.\d+)\s+wa,\s+(\d+\.\d+)\s+hi,\s+(\d+\.\d+)\s+si,\s+(\d+\.\d+)\s+st`) matches := re.FindStringSubmatch(line) if matches == nil { - logger.Errorf("Failed to parse CPU info: %s", line) + resourcesLogger.Errorf("Failed to parse CPU info: %s", line) return CPUInfo{} } @@ -306,7 +307,7 @@ func parseFloat(field string, value string) float64 { var result float64 result, err := strconv.ParseFloat(value, 64) if err != nil { - logger.Errorf("parseFloat failed to parse field %s: %v", field, err) + resourcesLogger.Errorf("parseFloat failed to parse field %s: %v", field, err) return -1 } @@ -316,7 +317,7 @@ func parseFloat(field string, value string) float64 { func parseInt(field string, value string) int { result, err := strconv.Atoi(value) if err != nil { - logger.Errorf("parseInt failed to parse field %s: %v", field, err) + resourcesLogger.Errorf("parseInt failed to parse field %s: %v", field, err) return -1 } return result diff --git a/x-pack/metricbeat/module/panw/system/system_types.go b/x-pack/metricbeat/module/panw/system/system_types.go index 4f821477ecb..41adce4697b 100644 --- a/x-pack/metricbeat/module/panw/system/system_types.go +++ b/x-pack/metricbeat/module/panw/system/system_types.go @@ -87,7 +87,7 @@ type ThermalSlot struct { type ThermalEntry struct { Slot int `xml:"slot"` Description string `xml:"description"` - Alarm bool `xml:"alarm"` + Alarm string `xml:"alarm"` DegreesCelsius float64 `xml:"DegreesC"` MinimumTemp float64 `xml:"min"` MaximumTemp float64 `xml:"max"` diff --git a/x-pack/metricbeat/module/panw/system/thermal.go b/x-pack/metricbeat/module/panw/system/thermal.go index 70c597ea776..161b72c0a2d 100644 --- a/x-pack/metricbeat/module/panw/system/thermal.go +++ b/x-pack/metricbeat/module/panw/system/thermal.go @@ -9,6 +9,7 @@ import ( "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/mapstr" ) @@ -17,7 +18,7 @@ const thermalQuery = " - TSi IP address of the IPsec tunnel + Traffic Selector Initiator IP. This is the local IP (0.0.0.0 means any IP address) - name: ipsec_tunnel.TSi_prefix type: keyword description: > - TSi prefix of the IPsec tunnel + Network prefix for the TSi IP, 0 means no specific network is defined. - name: ipsec_tunnel.TSi_proto type: keyword description: > - TSi protocol of the IPsec tunnel + Protocol associated with the TSi (0 means any protocol) - name: ipsec_tunnel.TSi_port type: long description: > - TSi port of the IPsec tunnel + Port number associated with TSi (0 means any port) - name: ipsec_tunnel.TSr_ip type: ip description: > - TSr IP address of the IPsec tunnel + Traffic Selector Responder IP. - name: ipsec_tunnel.TSr_prefix type: keyword description: > - TSr prefix of the IPsec tunnel + Network prefix for the TSr IP. Similar to TSi_prefix - name: ipsec_tunnel.TSr_proto type: keyword description: > @@ -171,7 +171,7 @@ - name: ipsec_tunnel.mode type: keyword description: > - Mode of the IPsec tunnel + This specifies the IPsec mode. e.g., 'tunl' - name: ipsec_tunnel.dh type: keyword description: > @@ -187,8 +187,8 @@ - name: ipsec_tunnel.life type: long description: > - Lifetime of the IPsec tunnel + The lifetime of the IPsec Security Association (SA) in seconds - name: ipsec_tunnel.kb type: long description: > - Key bytes of the IPsec tunnel \ No newline at end of file + Traffic volume limit for SA rekeying \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/vpn/gp_sessions.go b/x-pack/metricbeat/module/panw/vpn/gp_sessions.go index e4b54bab028..0037051740f 100644 --- a/x-pack/metricbeat/module/panw/vpn/gp_sessions.go +++ b/x-pack/metricbeat/module/panw/vpn/gp_sessions.go @@ -10,6 +10,7 @@ import ( "time" "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/x-pack/metricbeat/module/panw" "github.com/elastic/elastic-agent-libs/mapstr" ) @@ -18,7 +19,7 @@ const gpSessionsQuery = "" apiDebugMode: false diff --git a/x-pack/metricbeat/patch1.diff b/x-pack/metricbeat/patch1.diff deleted file mode 100644 index 823a6c5bc95..00000000000 --- a/x-pack/metricbeat/patch1.diff +++ /dev/null @@ -1,717 +0,0 @@ -diff --git a/go.mod b/go.mod -index a47bf7ec15..193648d401 100644 ---- a/go.mod -+++ b/go.mod -@@ -181,6 +181,7 @@ require ( - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.0 - github.com/Azure/azure-storage-blob-go v0.15.0 - github.com/Azure/go-autorest/autorest/adal v0.9.24 -+ github.com/PaloAltoNetworks/pango v0.10.2 - github.com/apache/arrow/go/v14 v14.0.2 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.13 -diff --git a/go.sum b/go.sum -index ec32ee823d..d9ce04d812 100644 ---- a/go.sum -+++ b/go.sum -@@ -215,6 +215,8 @@ github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbV - github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= - github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= - github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= -+github.com/PaloAltoNetworks/pango v0.10.2 h1:Tjn6vIzzAq6Dd7N0mDuiP8w8pz8k5W9zz/TTSUQCsQY= -+github.com/PaloAltoNetworks/pango v0.10.2/go.mod h1:GztcRnVLur7G+VFG7Z5ZKNFgScLtsycwPMp1qVebE5g= - github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= - github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= - github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -diff --git a/x-pack/metricbeat/module/panos/system/certificates.go b/x-pack/metricbeat/module/panos/system/certificates.go -index ca81bfcc91..1ae5c5cf39 100644 ---- a/x-pack/metricbeat/module/panos/system/certificates.go -+++ b/x-pack/metricbeat/module/panos/system/certificates.go -@@ -6,6 +6,8 @@ package system - - import ( - "encoding/xml" -+ "errors" -+ "fmt" - "regexp" - "strings" - "time" -@@ -20,29 +22,39 @@ func getCertificateEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to execute query: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) - } - -- events := formatCertificateEvents(m, response.Result) -+ if response.Result == "" { -+ return nil, fmt.Errorf("empty result from XML response") -+ } -+ -+ events, err := formatCertificateEvents(m, response.Result) -+ if err != nil { -+ return nil, fmt.Errorf("failed to format certificate events: %w", err) -+ } - - return events, nil - } - --func formatCertificateEvents(m *MetricSet, input string) []mb.Event { -- currentTime := time.Now() -+func formatCertificateEvents(m *MetricSet, input string) ([]mb.Event, error) { -+ timestamp := time.Now() -+ -+ certificates, err := parseCertificates(input) -+ if err != nil { -+ return nil, err -+ } - -- certificates := parseCertificates(input) - events := make([]mb.Event, 0, len(certificates)) - - for _, certificate := range certificates { - event := mb.Event{ -+ Timestamp: timestamp, - MetricSetFields: mapstr.M{ - "certificate.name": certificate.CertName, - "certificate.issuer": certificate.Issuer, -@@ -61,59 +73,78 @@ func formatCertificateEvents(m *MetricSet, input string) []mb.Event { - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } - - events = append(events, event) - } - -- return events -+ return events, nil - } - --func parseCertificates(input string) []Certificate { -+const ( -+ issuerPrefix = "issuer: " -+ issuerSubjectHashPrefix = "issuer-subjecthash: " -+ issuerKeyHashPrefix = "issuer-keyhash: " -+ dbTypePrefix = "db-type: " -+ dbExpDatePrefix = "db-exp-date: " -+ dbRevDatePrefix = "db-rev-date: " -+ dbSerialNoPrefix = "db-serialno: " -+ dbFilePrefix = "db-file: " -+ dbNamePrefix = "db-name: " -+ dbStatusPrefix = "db-status: " -+) -+ -+func parseCertificates(input string) ([]Certificate, error) { - lines := strings.Split(input, "\n") - pattern := `^[0-9A-Fa-f]{1,40}:[0-9A-Fa-f]{40}([0-9A-Fa-f]{24})?$` - regex := regexp.MustCompile(pattern) -- var certificates []Certificate -+ -+ certificates := make([]Certificate, 0) - var currentSN Certificate - - for _, line := range lines { - line = strings.TrimSpace(line) -- if regex.MatchString(line) { -+ switch { -+ case regex.MatchString(line): - if currentSN.CertName != "" { - certificates = append(certificates, currentSN) - currentSN = Certificate{} - } - currentSN.CertName = line -- } else if strings.HasPrefix(line, "issuer:") { -- currentSN.Issuer = strings.TrimPrefix(line, "issuer: ") -- } else if strings.HasPrefix(line, "issuer-subjecthash:") { -- currentSN.IssuerSubjectHash = strings.TrimPrefix(line, "issuer-subjecthash: ") -- } else if strings.HasPrefix(line, "issuer-keyhash:") { -- currentSN.IssuerKeyHash = strings.TrimPrefix(line, "issuer-keyhash: ") -- if strings.HasPrefix(currentSN.IssuerKeyHash, "issuer-keyhash:") { -+ case strings.HasPrefix(line, issuerPrefix): -+ currentSN.Issuer = strings.TrimPrefix(line, issuerPrefix) -+ case strings.HasPrefix(line, issuerSubjectHashPrefix): -+ currentSN.IssuerSubjectHash = strings.TrimPrefix(line, issuerSubjectHashPrefix) -+ case strings.HasPrefix(line, issuerKeyHashPrefix): -+ currentSN.IssuerKeyHash = strings.TrimPrefix(line, issuerKeyHashPrefix) -+ if strings.HasPrefix(currentSN.IssuerKeyHash, issuerKeyHashPrefix) { - currentSN.IssuerKeyHash = "" - } -- } else if strings.HasPrefix(line, "db-type:") { -- currentSN.DBType = strings.TrimPrefix(line, "db-type: ") -- } else if strings.HasPrefix(line, "db-exp-date:") { -- currentSN.DBExpDate = strings.TrimPrefix(line, "db-exp-date: ") -- } else if strings.HasPrefix(line, "db-rev-date:") { -- currentSN.DBRevDate = strings.TrimPrefix(line, "db-rev-date: ") -- } else if strings.HasPrefix(line, "db-serialno:") { -- currentSN.DBSerialNo = strings.TrimPrefix(line, "db-serialno: ") -- } else if strings.HasPrefix(line, "db-file:") { -- currentSN.DBFile = strings.TrimPrefix(line, "db-file: ") -- } else if strings.HasPrefix(line, "db-name:") { -- currentSN.DBName = strings.TrimPrefix(line, "db-name: ") -- } else if strings.HasPrefix(line, "db-status:") { -- currentSN.DBStatus = strings.TrimPrefix(line, "db-status: ") -+ case strings.HasPrefix(line, dbTypePrefix): -+ currentSN.DBType = strings.TrimPrefix(line, dbTypePrefix) -+ case strings.HasPrefix(line, dbExpDatePrefix): -+ currentSN.DBExpDate = strings.TrimPrefix(line, dbExpDatePrefix) -+ case strings.HasPrefix(line, dbRevDatePrefix): -+ currentSN.DBRevDate = strings.TrimPrefix(line, dbRevDatePrefix) -+ case strings.HasPrefix(line, dbSerialNoPrefix): -+ currentSN.DBSerialNo = strings.TrimPrefix(line, dbSerialNoPrefix) -+ case strings.HasPrefix(line, dbFilePrefix): -+ currentSN.DBFile = strings.TrimPrefix(line, dbFilePrefix) -+ case strings.HasPrefix(line, dbNamePrefix): -+ currentSN.DBName = strings.TrimPrefix(line, dbNamePrefix) -+ case strings.HasPrefix(line, dbStatusPrefix): -+ currentSN.DBStatus = strings.TrimPrefix(line, dbStatusPrefix) - } - } - -- if currentSN.Issuer != "" { -+ if currentSN.CertName != "" { - certificates = append(certificates, currentSN) - } - -- return certificates -+ if len(certificates) == 0 { -+ return nil, errors.New("no valid certificates found") -+ } -+ -+ return certificates, nil - } -diff --git a/x-pack/metricbeat/module/panos/system/fans.go b/x-pack/metricbeat/module/panos/system/fans.go -index 3e04299b2f..b725d83966 100644 ---- a/x-pack/metricbeat/module/panos/system/fans.go -+++ b/x-pack/metricbeat/module/panos/system/fans.go -@@ -6,6 +6,7 @@ package system - - import ( - "encoding/xml" -+ "fmt" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" -@@ -18,46 +19,46 @@ func getFanEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error querying fan data: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error unmarshaling fan data: %w", err) - } - -- events := formatFanEvents(m, &response) -- -- return events, nil -+ return formatFanEvents(m, &response), nil - } - - func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { -- log := m.Logger() -- events := make([]mb.Event, 0, len(response.Result.Fan.Slots)) -- currentTime := time.Now() -- var event mb.Event -+ if response == nil || len(response.Result.Fan.Slots) == 0 { -+ return nil -+ } -+ -+ events := make([]mb.Event, 0) -+ timestamp := time.Now() -+ - for _, slot := range response.Result.Fan.Slots { - for _, entry := range slot.Entries { -- log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) -- event = mb.Event{MetricSetFields: mapstr.M{ -- "fan.slot_number": entry.Slot, -- "fan.description": entry.Description, -- "fan.alarm": entry.Alarm, -- "fan.rpm": entry.RPMs, -- "fan.min_rpm": entry.Min, -- }, -+ m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "fan.slot_number": entry.Slot, -+ "fan.description": entry.Description, -+ "fan.alarm": entry.Alarm, -+ "fan.rpm": entry.RPMs, -+ "fan.min_rpm": entry.Min, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } -+ events = append(events, event) - } -- -- events = append(events, event) - } - - return events -diff --git a/x-pack/metricbeat/module/panos/system/filesystem.go b/x-pack/metricbeat/module/panos/system/filesystem.go -index 4adc63c3dc..e75eac63ef 100644 ---- a/x-pack/metricbeat/module/panos/system/filesystem.go -+++ b/x-pack/metricbeat/module/panos/system/filesystem.go -@@ -6,6 +6,7 @@ package system - - import ( - "encoding/xml" -+ "fmt" - "strings" - "time" - -@@ -20,39 +21,38 @@ func getFilesystemEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error querying filesystem info: %w", err) -+ } -+ -+ if len(output) == 0 { -+ return nil, fmt.Errorf("received empty output from filesystem query") - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error unmarshaling filesystem response: %w", err) - } - - filesystems := getFilesystems(response.Result.Data) -- events := formatFilesytemEvents(m, filesystems) -+ events := formatFilesystemEvents(m, filesystems) - - return events, nil - } - --/* --Result from the XML API call is basically linux df -h output: --Filesystem Size Used Avail Use% Mounted on --/dev/root 9.5G 4.0G 5.1G 44% / --none 2.5G 64K 2.5G 1% /dev --/dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg --/dev/sda6 7.6G 3.1G 4.2G 43% /opt/panrepo --tmpfs 2.5G 399M 2.1G 16% /dev/shm --cgroup_root 2.5G 0 2.5G 0% /cgroup --/dev/sda8 173G 63G 102G 39% /opt/panlogs --tmpfs 12M 44K 12M 1% /opt/pancfg/mgmt/ssl/private --*/ - func getFilesystems(input string) []Filesystem { - lines := strings.Split(input, "\n") - filesystems := make([]Filesystem, 0) - -- // Skip the first line which is the header -+ // Skip the first line which is the header: -+ // -+ // Example: -+ // Result from the XML API call is basically a command in Linux distribution i.e., "df -h"'s output: -+ // -+ // Filesystem Size Used Avail Use% Mounted on -+ // /dev/root 9.5G 4.0G 5.1G 44% / -+ // none 2.5G 64K 2.5G 1% /dev -+ // /dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg -+ // - for _, line := range lines[1:] { - fields := strings.Fields(line) - if len(fields) == 6 { -@@ -70,31 +70,35 @@ func getFilesystems(input string) []Filesystem { - return filesystems - } - --func formatFilesytemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { -- events := make([]mb.Event, 0, len(filesystems)) -+func formatFilesystemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { -+ if len(filesystems) == 0 { -+ return nil -+ } - -- currentTime := time.Now() -+ events := make([]mb.Event, 0, len(filesystems)) -+ timestamp := time.Now() - - for _, filesystem := range filesystems { -- event := mb.Event{MetricSetFields: mapstr.M{ -- "filesystem.name": filesystem.Name, -- "filesystem.size": filesystem.Size, -- "filesystem.used": filesystem.Used, -- "filesystem.available": filesystem.Avail, -- "filesystem.use_percent": filesystem.UsePerc, -- "filesystem.mounted": filesystem.Mounted, -- }, -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "filesystem.name": filesystem.Name, -+ "filesystem.size": filesystem.Size, -+ "filesystem.used": filesystem.Used, -+ "filesystem.available": filesystem.Avail, -+ "filesystem.use_percent": filesystem.UsePerc, -+ "filesystem.mounted": filesystem.Mounted, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } - - events = append(events, event) - } - - return events -- - } -diff --git a/x-pack/metricbeat/module/panos/system/license.go b/x-pack/metricbeat/module/panos/system/license.go -index d12f03b8c1..88ae64050d 100644 ---- a/x-pack/metricbeat/module/panos/system/license.go -+++ b/x-pack/metricbeat/module/panos/system/license.go -@@ -6,6 +6,7 @@ package system - - import ( - "encoding/xml" -+ "fmt" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" -@@ -18,48 +19,52 @@ func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to execute query: %w", err) -+ } -+ -+ if len(output) == 0 { -+ return nil, fmt.Errorf("empty response from PanOS") - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) - } - -- events := formatLicenseEvents(m, response.Result.Licenses) -- -- return events, nil -+ if len(response.Result.Licenses) == 0 { -+ m.logger.Warn("No licenses found in the response") -+ return nil, nil -+ } - -+ return formatLicenseEvents(m, response.Result.Licenses), nil - } - - func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { - events := make([]mb.Event, 0, len(licenses)) -- -- currentTime := time.Now() -+ timestamp := time.Now() - - for _, license := range licenses { -- event := mb.Event{MetricSetFields: mapstr.M{ -- "license.feature": license.Feature, -- "license.escription": license.Description, -- "license.serial": license.Serial, -- "license.issued": license.Issued, -- "license.expires": license.Expires, -- "license.expired": license.Expired, -- "license.auth_code": license.AuthCode, -- }, -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "license.feature": license.Feature, -+ "license.description": license.Description, // Fixed typo -+ "license.serial": license.Serial, -+ "license.issued": license.Issued, -+ "license.expires": license.Expires, -+ "license.expired": license.Expired, -+ "license.auth_code": license.AuthCode, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } - - events = append(events, event) - } - - return events -- - } -diff --git a/x-pack/metricbeat/module/panos/system/power.go b/x-pack/metricbeat/module/panos/system/power.go -index d5a4aa8487..a7540ad618 100644 ---- a/x-pack/metricbeat/module/panos/system/power.go -+++ b/x-pack/metricbeat/module/panos/system/power.go -@@ -6,27 +6,31 @@ package system - - import ( - "encoding/xml" -+ "fmt" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" - ) - -+// getPowerEvents retrieves power-related events from a PAN-OS device. - func getPowerEvents(m *MetricSet) ([]mb.Event, error) { -- - query := "" - var response PowerResponse - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to execute operation: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) -+ } -+ -+ if len(response.Result.Power.Slots) == 0 { -+ m.logger.Warn("No power events found in the response") -+ return nil, nil - } - - events := formatPowerEvents(m, &response) -@@ -35,32 +39,31 @@ func getPowerEvents(m *MetricSet) ([]mb.Event, error) { - } - - func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { -- log := m.Logger() -- events := make([]mb.Event, 0, len(response.Result.Power.Slots)) -- currentTime := time.Now() -- var event mb.Event -+ events := make([]mb.Event, 0) -+ timestamp := time.Now() -+ - for _, slot := range response.Result.Power.Slots { - for _, entry := range slot.Entries { -- log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) -- event = mb.Event{MetricSetFields: mapstr.M{ -- -- "power.slot_number": entry.Slot, -- "power.description": entry.Description, -- "power.alarm": entry.Alarm, -- "power.volts": entry.Volts, -- "power.minimum_volts": entry.MinimumVolts, -- "power.maximum_volts": entry.MaximumVolts, -- }, -+ m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "power.slot_number": entry.Slot, -+ "power.description": entry.Description, -+ "power.alarm": entry.Alarm, -+ "power.volts": entry.Volts, -+ "power.minimum_volts": entry.MinimumVolts, -+ "power.maximum_volts": entry.MaximumVolts, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } -+ events = append(events, event) - } -- -- events = append(events, event) - } - - return events -diff --git a/x-pack/metricbeat/module/panos/system/resources.go b/x-pack/metricbeat/module/panos/system/resources.go -index 1ad18bb92b..6f9a2b6716 100644 ---- a/x-pack/metricbeat/module/panos/system/resources.go -+++ b/x-pack/metricbeat/module/panos/system/resources.go -@@ -16,19 +16,17 @@ import ( - ) - - func getResourceEvents(m *MetricSet) ([]mb.Event, error) { -- var response ResourceResponse - query := "" - -- output, err := m.client.Op(query, vsys, nil, nil) -+ var response ResourceResponse -+ output, err := m.client.Op(query, vsys, nil, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to execute operation: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) - } - - events := formatResourceEvents(m, response.Result) -@@ -62,8 +60,8 @@ MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem - 2 20 0 0 0 0 S 0.0 0.0 0:00.83 kthreadd - */ - func formatResourceEvents(m *MetricSet, input string) []mb.Event { -- currentTime := time.Now() -- events := make([]mb.Event, 0, 1) -+ timestamp := time.Now() -+ events := make([]mb.Event, 0) - - // We only need the top 5 lines - lines := strings.Split(input, "\n") -@@ -75,42 +73,57 @@ func formatResourceEvents(m *MetricSet, input string) []mb.Event { - memoryInfo := parseMemoryInfo(lines[3]) - swapInfo := parseSwapInfo(lines[4]) - -- event := mb.Event{MetricSetFields: mapstr.M{ -- "uptime.days": systemInfo.Uptime.Days, -- "uptime.hours": systemInfo.Uptime.Hours, -- "user_count": systemInfo.UserCount, -- "load_average.1m": systemInfo.LoadAverage.one_minute, -- "load_average.5m": systemInfo.LoadAverage.five_minute, -- "load_average.15m": systemInfo.LoadAverage.fifteen_minute, -- "tasks.total": taskInfo.Total, -- "tasks.running": taskInfo.Running, -- "tasks.sleeping": taskInfo.Sleeping, -- "tasks.stopped": taskInfo.Stopped, -- "tasks.zombie": taskInfo.Zombie, -- "cpu.user": cpuInfo.User, -- "cpu.system": cpuInfo.System, -- "cpu.nice": cpuInfo.Nice, -- "cpu.idle": cpuInfo.Idle, -- "cpu.wait": cpuInfo.Wait, -- "cpu.hi": cpuInfo.Hi, -- "cpu.system_int": cpuInfo.SystemInt, -- "cpu.steal": cpuInfo.Steal, -- "memory.total": memoryInfo.Total, -- "memory.free": memoryInfo.Free, -- "memory.used": memoryInfo.Used, -- "memory.buffer_cache": memoryInfo.BufferCache, -- "swap.total": swapInfo.Total, -- "swap.free": swapInfo.Free, -- "swap.used": swapInfo.Used, -- "swap.available": swapInfo.Available, -- }, -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "uptime": mapstr.M{ -+ "days": systemInfo.Uptime.Days, -+ "hours": systemInfo.Uptime.Hours, -+ "minutes": systemInfo.Uptime.Minutes, -+ }, -+ "user_count": systemInfo.UserCount, -+ "load_average": mapstr.M{ -+ "1m": systemInfo.LoadAverage.OneMinute, -+ "5m": systemInfo.LoadAverage.FiveMinute, -+ "15m": systemInfo.LoadAverage.FifteenMinute, -+ }, -+ "tasks": mapstr.M{ -+ "total": taskInfo.Total, -+ "running": taskInfo.Running, -+ "sleeping": taskInfo.Sleeping, -+ "stopped": taskInfo.Stopped, -+ "zombie": taskInfo.Zombie, -+ }, -+ "cpu": mapstr.M{ -+ "user": cpuInfo.User, -+ "system": cpuInfo.System, -+ "nice": cpuInfo.Nice, -+ "idle": cpuInfo.Idle, -+ "wait": cpuInfo.Wait, -+ "hi": cpuInfo.Hi, -+ "system_int": cpuInfo.SystemInt, -+ "steal": cpuInfo.Steal, -+ }, -+ "memory": mapstr.M{ -+ "total": memoryInfo.Total, -+ "free": memoryInfo.Free, -+ "used": memoryInfo.Used, -+ "buffer_cache": memoryInfo.BufferCache, -+ }, -+ "swap": mapstr.M{ -+ "total": swapInfo.Total, -+ "free": swapInfo.Free, -+ "used": swapInfo.Used, -+ "available": swapInfo.Available, -+ }, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } - - events = append(events, event) - return events -diff --git a/x-pack/metricbeat/module/panos/system/system_types.go b/x-pack/metricbeat/module/panos/system/system_types.go -index d130b9a2e7..4f821477ec 100644 ---- a/x-pack/metricbeat/module/panos/system/system_types.go -+++ b/x-pack/metricbeat/module/panos/system/system_types.go -@@ -15,9 +15,9 @@ type ResourceResponse struct { - } - - type SystemLoad struct { -- one_minute float64 -- five_minute float64 -- fifteen_minute float64 -+ OneMinute float64 -+ FiveMinute float64 -+ FifteenMinute float64 - } - - type Uptime struct { diff --git a/x-pack/metricbeat/patch2.diff b/x-pack/metricbeat/patch2.diff deleted file mode 100644 index 823a6c5bc95..00000000000 --- a/x-pack/metricbeat/patch2.diff +++ /dev/null @@ -1,717 +0,0 @@ -diff --git a/go.mod b/go.mod -index a47bf7ec15..193648d401 100644 ---- a/go.mod -+++ b/go.mod -@@ -181,6 +181,7 @@ require ( - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.0 - github.com/Azure/azure-storage-blob-go v0.15.0 - github.com/Azure/go-autorest/autorest/adal v0.9.24 -+ github.com/PaloAltoNetworks/pango v0.10.2 - github.com/apache/arrow/go/v14 v14.0.2 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.13 -diff --git a/go.sum b/go.sum -index ec32ee823d..d9ce04d812 100644 ---- a/go.sum -+++ b/go.sum -@@ -215,6 +215,8 @@ github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbV - github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= - github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= - github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= -+github.com/PaloAltoNetworks/pango v0.10.2 h1:Tjn6vIzzAq6Dd7N0mDuiP8w8pz8k5W9zz/TTSUQCsQY= -+github.com/PaloAltoNetworks/pango v0.10.2/go.mod h1:GztcRnVLur7G+VFG7Z5ZKNFgScLtsycwPMp1qVebE5g= - github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= - github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= - github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -diff --git a/x-pack/metricbeat/module/panos/system/certificates.go b/x-pack/metricbeat/module/panos/system/certificates.go -index ca81bfcc91..1ae5c5cf39 100644 ---- a/x-pack/metricbeat/module/panos/system/certificates.go -+++ b/x-pack/metricbeat/module/panos/system/certificates.go -@@ -6,6 +6,8 @@ package system - - import ( - "encoding/xml" -+ "errors" -+ "fmt" - "regexp" - "strings" - "time" -@@ -20,29 +22,39 @@ func getCertificateEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to execute query: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) - } - -- events := formatCertificateEvents(m, response.Result) -+ if response.Result == "" { -+ return nil, fmt.Errorf("empty result from XML response") -+ } -+ -+ events, err := formatCertificateEvents(m, response.Result) -+ if err != nil { -+ return nil, fmt.Errorf("failed to format certificate events: %w", err) -+ } - - return events, nil - } - --func formatCertificateEvents(m *MetricSet, input string) []mb.Event { -- currentTime := time.Now() -+func formatCertificateEvents(m *MetricSet, input string) ([]mb.Event, error) { -+ timestamp := time.Now() -+ -+ certificates, err := parseCertificates(input) -+ if err != nil { -+ return nil, err -+ } - -- certificates := parseCertificates(input) - events := make([]mb.Event, 0, len(certificates)) - - for _, certificate := range certificates { - event := mb.Event{ -+ Timestamp: timestamp, - MetricSetFields: mapstr.M{ - "certificate.name": certificate.CertName, - "certificate.issuer": certificate.Issuer, -@@ -61,59 +73,78 @@ func formatCertificateEvents(m *MetricSet, input string) []mb.Event { - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } - - events = append(events, event) - } - -- return events -+ return events, nil - } - --func parseCertificates(input string) []Certificate { -+const ( -+ issuerPrefix = "issuer: " -+ issuerSubjectHashPrefix = "issuer-subjecthash: " -+ issuerKeyHashPrefix = "issuer-keyhash: " -+ dbTypePrefix = "db-type: " -+ dbExpDatePrefix = "db-exp-date: " -+ dbRevDatePrefix = "db-rev-date: " -+ dbSerialNoPrefix = "db-serialno: " -+ dbFilePrefix = "db-file: " -+ dbNamePrefix = "db-name: " -+ dbStatusPrefix = "db-status: " -+) -+ -+func parseCertificates(input string) ([]Certificate, error) { - lines := strings.Split(input, "\n") - pattern := `^[0-9A-Fa-f]{1,40}:[0-9A-Fa-f]{40}([0-9A-Fa-f]{24})?$` - regex := regexp.MustCompile(pattern) -- var certificates []Certificate -+ -+ certificates := make([]Certificate, 0) - var currentSN Certificate - - for _, line := range lines { - line = strings.TrimSpace(line) -- if regex.MatchString(line) { -+ switch { -+ case regex.MatchString(line): - if currentSN.CertName != "" { - certificates = append(certificates, currentSN) - currentSN = Certificate{} - } - currentSN.CertName = line -- } else if strings.HasPrefix(line, "issuer:") { -- currentSN.Issuer = strings.TrimPrefix(line, "issuer: ") -- } else if strings.HasPrefix(line, "issuer-subjecthash:") { -- currentSN.IssuerSubjectHash = strings.TrimPrefix(line, "issuer-subjecthash: ") -- } else if strings.HasPrefix(line, "issuer-keyhash:") { -- currentSN.IssuerKeyHash = strings.TrimPrefix(line, "issuer-keyhash: ") -- if strings.HasPrefix(currentSN.IssuerKeyHash, "issuer-keyhash:") { -+ case strings.HasPrefix(line, issuerPrefix): -+ currentSN.Issuer = strings.TrimPrefix(line, issuerPrefix) -+ case strings.HasPrefix(line, issuerSubjectHashPrefix): -+ currentSN.IssuerSubjectHash = strings.TrimPrefix(line, issuerSubjectHashPrefix) -+ case strings.HasPrefix(line, issuerKeyHashPrefix): -+ currentSN.IssuerKeyHash = strings.TrimPrefix(line, issuerKeyHashPrefix) -+ if strings.HasPrefix(currentSN.IssuerKeyHash, issuerKeyHashPrefix) { - currentSN.IssuerKeyHash = "" - } -- } else if strings.HasPrefix(line, "db-type:") { -- currentSN.DBType = strings.TrimPrefix(line, "db-type: ") -- } else if strings.HasPrefix(line, "db-exp-date:") { -- currentSN.DBExpDate = strings.TrimPrefix(line, "db-exp-date: ") -- } else if strings.HasPrefix(line, "db-rev-date:") { -- currentSN.DBRevDate = strings.TrimPrefix(line, "db-rev-date: ") -- } else if strings.HasPrefix(line, "db-serialno:") { -- currentSN.DBSerialNo = strings.TrimPrefix(line, "db-serialno: ") -- } else if strings.HasPrefix(line, "db-file:") { -- currentSN.DBFile = strings.TrimPrefix(line, "db-file: ") -- } else if strings.HasPrefix(line, "db-name:") { -- currentSN.DBName = strings.TrimPrefix(line, "db-name: ") -- } else if strings.HasPrefix(line, "db-status:") { -- currentSN.DBStatus = strings.TrimPrefix(line, "db-status: ") -+ case strings.HasPrefix(line, dbTypePrefix): -+ currentSN.DBType = strings.TrimPrefix(line, dbTypePrefix) -+ case strings.HasPrefix(line, dbExpDatePrefix): -+ currentSN.DBExpDate = strings.TrimPrefix(line, dbExpDatePrefix) -+ case strings.HasPrefix(line, dbRevDatePrefix): -+ currentSN.DBRevDate = strings.TrimPrefix(line, dbRevDatePrefix) -+ case strings.HasPrefix(line, dbSerialNoPrefix): -+ currentSN.DBSerialNo = strings.TrimPrefix(line, dbSerialNoPrefix) -+ case strings.HasPrefix(line, dbFilePrefix): -+ currentSN.DBFile = strings.TrimPrefix(line, dbFilePrefix) -+ case strings.HasPrefix(line, dbNamePrefix): -+ currentSN.DBName = strings.TrimPrefix(line, dbNamePrefix) -+ case strings.HasPrefix(line, dbStatusPrefix): -+ currentSN.DBStatus = strings.TrimPrefix(line, dbStatusPrefix) - } - } - -- if currentSN.Issuer != "" { -+ if currentSN.CertName != "" { - certificates = append(certificates, currentSN) - } - -- return certificates -+ if len(certificates) == 0 { -+ return nil, errors.New("no valid certificates found") -+ } -+ -+ return certificates, nil - } -diff --git a/x-pack/metricbeat/module/panos/system/fans.go b/x-pack/metricbeat/module/panos/system/fans.go -index 3e04299b2f..b725d83966 100644 ---- a/x-pack/metricbeat/module/panos/system/fans.go -+++ b/x-pack/metricbeat/module/panos/system/fans.go -@@ -6,6 +6,7 @@ package system - - import ( - "encoding/xml" -+ "fmt" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" -@@ -18,46 +19,46 @@ func getFanEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error querying fan data: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error unmarshaling fan data: %w", err) - } - -- events := formatFanEvents(m, &response) -- -- return events, nil -+ return formatFanEvents(m, &response), nil - } - - func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { -- log := m.Logger() -- events := make([]mb.Event, 0, len(response.Result.Fan.Slots)) -- currentTime := time.Now() -- var event mb.Event -+ if response == nil || len(response.Result.Fan.Slots) == 0 { -+ return nil -+ } -+ -+ events := make([]mb.Event, 0) -+ timestamp := time.Now() -+ - for _, slot := range response.Result.Fan.Slots { - for _, entry := range slot.Entries { -- log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) -- event = mb.Event{MetricSetFields: mapstr.M{ -- "fan.slot_number": entry.Slot, -- "fan.description": entry.Description, -- "fan.alarm": entry.Alarm, -- "fan.rpm": entry.RPMs, -- "fan.min_rpm": entry.Min, -- }, -+ m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "fan.slot_number": entry.Slot, -+ "fan.description": entry.Description, -+ "fan.alarm": entry.Alarm, -+ "fan.rpm": entry.RPMs, -+ "fan.min_rpm": entry.Min, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } -+ events = append(events, event) - } -- -- events = append(events, event) - } - - return events -diff --git a/x-pack/metricbeat/module/panos/system/filesystem.go b/x-pack/metricbeat/module/panos/system/filesystem.go -index 4adc63c3dc..e75eac63ef 100644 ---- a/x-pack/metricbeat/module/panos/system/filesystem.go -+++ b/x-pack/metricbeat/module/panos/system/filesystem.go -@@ -6,6 +6,7 @@ package system - - import ( - "encoding/xml" -+ "fmt" - "strings" - "time" - -@@ -20,39 +21,38 @@ func getFilesystemEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error querying filesystem info: %w", err) -+ } -+ -+ if len(output) == 0 { -+ return nil, fmt.Errorf("received empty output from filesystem query") - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error unmarshaling filesystem response: %w", err) - } - - filesystems := getFilesystems(response.Result.Data) -- events := formatFilesytemEvents(m, filesystems) -+ events := formatFilesystemEvents(m, filesystems) - - return events, nil - } - --/* --Result from the XML API call is basically linux df -h output: --Filesystem Size Used Avail Use% Mounted on --/dev/root 9.5G 4.0G 5.1G 44% / --none 2.5G 64K 2.5G 1% /dev --/dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg --/dev/sda6 7.6G 3.1G 4.2G 43% /opt/panrepo --tmpfs 2.5G 399M 2.1G 16% /dev/shm --cgroup_root 2.5G 0 2.5G 0% /cgroup --/dev/sda8 173G 63G 102G 39% /opt/panlogs --tmpfs 12M 44K 12M 1% /opt/pancfg/mgmt/ssl/private --*/ - func getFilesystems(input string) []Filesystem { - lines := strings.Split(input, "\n") - filesystems := make([]Filesystem, 0) - -- // Skip the first line which is the header -+ // Skip the first line which is the header: -+ // -+ // Example: -+ // Result from the XML API call is basically a command in Linux distribution i.e., "df -h"'s output: -+ // -+ // Filesystem Size Used Avail Use% Mounted on -+ // /dev/root 9.5G 4.0G 5.1G 44% / -+ // none 2.5G 64K 2.5G 1% /dev -+ // /dev/sda5 19G 9.1G 9.0G 51% /opt/pancfg -+ // - for _, line := range lines[1:] { - fields := strings.Fields(line) - if len(fields) == 6 { -@@ -70,31 +70,35 @@ func getFilesystems(input string) []Filesystem { - return filesystems - } - --func formatFilesytemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { -- events := make([]mb.Event, 0, len(filesystems)) -+func formatFilesystemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { -+ if len(filesystems) == 0 { -+ return nil -+ } - -- currentTime := time.Now() -+ events := make([]mb.Event, 0, len(filesystems)) -+ timestamp := time.Now() - - for _, filesystem := range filesystems { -- event := mb.Event{MetricSetFields: mapstr.M{ -- "filesystem.name": filesystem.Name, -- "filesystem.size": filesystem.Size, -- "filesystem.used": filesystem.Used, -- "filesystem.available": filesystem.Avail, -- "filesystem.use_percent": filesystem.UsePerc, -- "filesystem.mounted": filesystem.Mounted, -- }, -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "filesystem.name": filesystem.Name, -+ "filesystem.size": filesystem.Size, -+ "filesystem.used": filesystem.Used, -+ "filesystem.available": filesystem.Avail, -+ "filesystem.use_percent": filesystem.UsePerc, -+ "filesystem.mounted": filesystem.Mounted, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } - - events = append(events, event) - } - - return events -- - } -diff --git a/x-pack/metricbeat/module/panos/system/license.go b/x-pack/metricbeat/module/panos/system/license.go -index d12f03b8c1..88ae64050d 100644 ---- a/x-pack/metricbeat/module/panos/system/license.go -+++ b/x-pack/metricbeat/module/panos/system/license.go -@@ -6,6 +6,7 @@ package system - - import ( - "encoding/xml" -+ "fmt" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" -@@ -18,48 +19,52 @@ func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to execute query: %w", err) -+ } -+ -+ if len(output) == 0 { -+ return nil, fmt.Errorf("empty response from PanOS") - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) - } - -- events := formatLicenseEvents(m, response.Result.Licenses) -- -- return events, nil -+ if len(response.Result.Licenses) == 0 { -+ m.logger.Warn("No licenses found in the response") -+ return nil, nil -+ } - -+ return formatLicenseEvents(m, response.Result.Licenses), nil - } - - func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { - events := make([]mb.Event, 0, len(licenses)) -- -- currentTime := time.Now() -+ timestamp := time.Now() - - for _, license := range licenses { -- event := mb.Event{MetricSetFields: mapstr.M{ -- "license.feature": license.Feature, -- "license.escription": license.Description, -- "license.serial": license.Serial, -- "license.issued": license.Issued, -- "license.expires": license.Expires, -- "license.expired": license.Expired, -- "license.auth_code": license.AuthCode, -- }, -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "license.feature": license.Feature, -+ "license.description": license.Description, // Fixed typo -+ "license.serial": license.Serial, -+ "license.issued": license.Issued, -+ "license.expires": license.Expires, -+ "license.expired": license.Expired, -+ "license.auth_code": license.AuthCode, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } - - events = append(events, event) - } - - return events -- - } -diff --git a/x-pack/metricbeat/module/panos/system/power.go b/x-pack/metricbeat/module/panos/system/power.go -index d5a4aa8487..a7540ad618 100644 ---- a/x-pack/metricbeat/module/panos/system/power.go -+++ b/x-pack/metricbeat/module/panos/system/power.go -@@ -6,27 +6,31 @@ package system - - import ( - "encoding/xml" -+ "fmt" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" - ) - -+// getPowerEvents retrieves power-related events from a PAN-OS device. - func getPowerEvents(m *MetricSet) ([]mb.Event, error) { -- - query := "" - var response PowerResponse - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to execute operation: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) -+ } -+ -+ if len(response.Result.Power.Slots) == 0 { -+ m.logger.Warn("No power events found in the response") -+ return nil, nil - } - - events := formatPowerEvents(m, &response) -@@ -35,32 +39,31 @@ func getPowerEvents(m *MetricSet) ([]mb.Event, error) { - } - - func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { -- log := m.Logger() -- events := make([]mb.Event, 0, len(response.Result.Power.Slots)) -- currentTime := time.Now() -- var event mb.Event -+ events := make([]mb.Event, 0) -+ timestamp := time.Now() -+ - for _, slot := range response.Result.Power.Slots { - for _, entry := range slot.Entries { -- log.Debugf("Processing slot %d entry %+v", entry.Slot, entry) -- event = mb.Event{MetricSetFields: mapstr.M{ -- -- "power.slot_number": entry.Slot, -- "power.description": entry.Description, -- "power.alarm": entry.Alarm, -- "power.volts": entry.Volts, -- "power.minimum_volts": entry.MinimumVolts, -- "power.maximum_volts": entry.MaximumVolts, -- }, -+ m.Logger().Debugf("Processing slot %d entry %+v", entry.Slot, entry) -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "power.slot_number": entry.Slot, -+ "power.description": entry.Description, -+ "power.alarm": entry.Alarm, -+ "power.volts": entry.Volts, -+ "power.minimum_volts": entry.MinimumVolts, -+ "power.maximum_volts": entry.MaximumVolts, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } -+ events = append(events, event) - } -- -- events = append(events, event) - } - - return events -diff --git a/x-pack/metricbeat/module/panos/system/resources.go b/x-pack/metricbeat/module/panos/system/resources.go -index 1ad18bb92b..6f9a2b6716 100644 ---- a/x-pack/metricbeat/module/panos/system/resources.go -+++ b/x-pack/metricbeat/module/panos/system/resources.go -@@ -16,19 +16,17 @@ import ( - ) - - func getResourceEvents(m *MetricSet) ([]mb.Event, error) { -- var response ResourceResponse - query := "" - -- output, err := m.client.Op(query, vsys, nil, nil) -+ var response ResourceResponse -+ output, err := m.client.Op(query, vsys, nil, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to execute operation: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("failed to unmarshal XML response: %w", err) - } - - events := formatResourceEvents(m, response.Result) -@@ -62,8 +60,8 @@ MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem - 2 20 0 0 0 0 S 0.0 0.0 0:00.83 kthreadd - */ - func formatResourceEvents(m *MetricSet, input string) []mb.Event { -- currentTime := time.Now() -- events := make([]mb.Event, 0, 1) -+ timestamp := time.Now() -+ events := make([]mb.Event, 0) - - // We only need the top 5 lines - lines := strings.Split(input, "\n") -@@ -75,42 +73,57 @@ func formatResourceEvents(m *MetricSet, input string) []mb.Event { - memoryInfo := parseMemoryInfo(lines[3]) - swapInfo := parseSwapInfo(lines[4]) - -- event := mb.Event{MetricSetFields: mapstr.M{ -- "uptime.days": systemInfo.Uptime.Days, -- "uptime.hours": systemInfo.Uptime.Hours, -- "user_count": systemInfo.UserCount, -- "load_average.1m": systemInfo.LoadAverage.one_minute, -- "load_average.5m": systemInfo.LoadAverage.five_minute, -- "load_average.15m": systemInfo.LoadAverage.fifteen_minute, -- "tasks.total": taskInfo.Total, -- "tasks.running": taskInfo.Running, -- "tasks.sleeping": taskInfo.Sleeping, -- "tasks.stopped": taskInfo.Stopped, -- "tasks.zombie": taskInfo.Zombie, -- "cpu.user": cpuInfo.User, -- "cpu.system": cpuInfo.System, -- "cpu.nice": cpuInfo.Nice, -- "cpu.idle": cpuInfo.Idle, -- "cpu.wait": cpuInfo.Wait, -- "cpu.hi": cpuInfo.Hi, -- "cpu.system_int": cpuInfo.SystemInt, -- "cpu.steal": cpuInfo.Steal, -- "memory.total": memoryInfo.Total, -- "memory.free": memoryInfo.Free, -- "memory.used": memoryInfo.Used, -- "memory.buffer_cache": memoryInfo.BufferCache, -- "swap.total": swapInfo.Total, -- "swap.free": swapInfo.Free, -- "swap.used": swapInfo.Used, -- "swap.available": swapInfo.Available, -- }, -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "uptime": mapstr.M{ -+ "days": systemInfo.Uptime.Days, -+ "hours": systemInfo.Uptime.Hours, -+ "minutes": systemInfo.Uptime.Minutes, -+ }, -+ "user_count": systemInfo.UserCount, -+ "load_average": mapstr.M{ -+ "1m": systemInfo.LoadAverage.OneMinute, -+ "5m": systemInfo.LoadAverage.FiveMinute, -+ "15m": systemInfo.LoadAverage.FifteenMinute, -+ }, -+ "tasks": mapstr.M{ -+ "total": taskInfo.Total, -+ "running": taskInfo.Running, -+ "sleeping": taskInfo.Sleeping, -+ "stopped": taskInfo.Stopped, -+ "zombie": taskInfo.Zombie, -+ }, -+ "cpu": mapstr.M{ -+ "user": cpuInfo.User, -+ "system": cpuInfo.System, -+ "nice": cpuInfo.Nice, -+ "idle": cpuInfo.Idle, -+ "wait": cpuInfo.Wait, -+ "hi": cpuInfo.Hi, -+ "system_int": cpuInfo.SystemInt, -+ "steal": cpuInfo.Steal, -+ }, -+ "memory": mapstr.M{ -+ "total": memoryInfo.Total, -+ "free": memoryInfo.Free, -+ "used": memoryInfo.Used, -+ "buffer_cache": memoryInfo.BufferCache, -+ }, -+ "swap": mapstr.M{ -+ "total": swapInfo.Total, -+ "free": swapInfo.Free, -+ "used": swapInfo.Used, -+ "available": swapInfo.Available, -+ }, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } - - events = append(events, event) - return events -diff --git a/x-pack/metricbeat/module/panos/system/system_types.go b/x-pack/metricbeat/module/panos/system/system_types.go -index d130b9a2e7..4f821477ec 100644 ---- a/x-pack/metricbeat/module/panos/system/system_types.go -+++ b/x-pack/metricbeat/module/panos/system/system_types.go -@@ -15,9 +15,9 @@ type ResourceResponse struct { - } - - type SystemLoad struct { -- one_minute float64 -- five_minute float64 -- fifteen_minute float64 -+ OneMinute float64 -+ FiveMinute float64 -+ FifteenMinute float64 - } - - type Uptime struct { diff --git a/x-pack/metricbeat/x.diff b/x-pack/metricbeat/x.diff deleted file mode 100644 index c739264906e..00000000000 --- a/x-pack/metricbeat/x.diff +++ /dev/null @@ -1,429 +0,0 @@ -diff --git a/go.mod b/go.mod -index a47bf7ec15..193648d401 100644 ---- a/go.mod -+++ b/go.mod -@@ -181,6 +181,7 @@ require ( - github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.0 - github.com/Azure/azure-storage-blob-go v0.15.0 - github.com/Azure/go-autorest/autorest/adal v0.9.24 -+ github.com/PaloAltoNetworks/pango v0.10.2 - github.com/apache/arrow/go/v14 v14.0.2 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.13 -diff --git a/go.sum b/go.sum -index ec32ee823d..d9ce04d812 100644 ---- a/go.sum -+++ b/go.sum -@@ -215,6 +215,8 @@ github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbV - github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= - github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= - github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= -+github.com/PaloAltoNetworks/pango v0.10.2 h1:Tjn6vIzzAq6Dd7N0mDuiP8w8pz8k5W9zz/TTSUQCsQY= -+github.com/PaloAltoNetworks/pango v0.10.2/go.mod h1:GztcRnVLur7G+VFG7Z5ZKNFgScLtsycwPMp1qVebE5g= - github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= - github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= - github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -diff --git a/x-pack/metricbeat/module/panos/client.go b/x-pack/metricbeat/module/panos/client.go -index a781b99871..e01cd941d7 100644 ---- a/x-pack/metricbeat/module/panos/client.go -+++ b/x-pack/metricbeat/module/panos/client.go -@@ -6,6 +6,7 @@ package panos - - import ( - "flag" -+ "fmt" - - "github.com/PaloAltoNetworks/pango" - ) -@@ -37,7 +38,7 @@ func GetPanosClient(config *Config) (PanosClient, error) { - firewall := pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - err := firewall.Initialize() - if err != nil { -- return nil, err -+ return nil, fmt.Errorf("error initializing firewall client: %w", err) - } - // Instantiate PanosFirewallClient - return &PanosFirewallClient{Firewall: firewall}, nil -diff --git a/x-pack/metricbeat/module/panos/vpn/gp_sessions.go b/x-pack/metricbeat/module/panos/vpn/gp_sessions.go -index ea1b8c31b6..af7d858fa1 100644 ---- a/x-pack/metricbeat/module/panos/vpn/gp_sessions.go -+++ b/x-pack/metricbeat/module/panos/vpn/gp_sessions.go -@@ -6,73 +6,77 @@ package vpn - - import ( - "encoding/xml" -+ "fmt" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/elastic/elastic-agent-libs/mapstr" - ) - -+const gpSessionsQuery = "" -+ - func getGlobalProtectSessionEvents(m *MetricSet) ([]mb.Event, error) { -- query := "" - var response GPSessionsResponse - -- output, err := m.client.Op(query, vsys, nil, nil) -+ output, err := m.client.Op(gpSessionsQuery, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error querying GlobalProtect sessions: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error unmarshaling GlobalProtect sessions response: %w", err) - } - - events := formatGPSessionEvents(m, response.Result.Sessions) - - return events, nil -- - } - - func formatGPSessionEvents(m *MetricSet, sessions []GPSession) []mb.Event { -- events := make([]mb.Event, 0, len(sessions)) -+ if sessions == nil { -+ return nil -+ } - -- currentTime := time.Now() -+ events := make([]mb.Event, 0, len(sessions)) -+ timestamp := time.Now() - - for _, session := range sessions { -- event := mb.Event{MetricSetFields: mapstr.M{ -- "globalprotect.domain": session.Domain, -- "globalprotect.is_local": session.IsLocal, -- "globalprotect.username": session.Username, -- "globalprotect.rimary_username": session.PrimaryUsername, -- "globalprotect.region_for_config": session.RegionForConfig, -- "globalprotect.ource_region": session.SourceRegion, -- "globalprotect.computer": session.Computer, -- "globalprotect.client": session.Client, -- "globalprotect.vpn_type": session.VPNType, -- "globalprotect.host_id": session.HostID, -- "globalprotect.app_version": session.AppVersion, -- "globalprotect.virtual_ip": session.VirtualIP, -- "globalprotect.virtual_ipv6": session.VirtualIPv6, -- "globalprotect.public_ip": session.PublicIP, -- "globalprotect.public_ipv6": session.PublicIPv6, -- "globalprotect.tunnel_type": session.TunnelType, -- "globalprotect.public_connection_ipv6": session.PublicConnectionIPv6, -- "globalprotect.lient_ip": session.ClientIP, -- "globalprotect.login_time": session.LoginTime, -- "globalprotect.login_time_utc": session.LoginTimeUTC, -- "globalprotect.lifetime": session.Lifetime, -- "globalprotect.request_login": session.RequestLogin, -- "globalprotect.request_get_config": session.RequestGetConfig, -- "globalprotect.request_sslvpn_connect": session.RequestSSLVPNConnect, -- }, -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "globalprotect.domain": session.Domain, -+ "globalprotect.is_local": session.IsLocal, -+ "globalprotect.username": session.Username, -+ "globalprotect.primary_username": session.PrimaryUsername, -+ "globalprotect.region_for_config": session.RegionForConfig, -+ "globalprotect.source_region": session.SourceRegion, -+ "globalprotect.computer": session.Computer, -+ "globalprotect.client": session.Client, -+ "globalprotect.vpn_type": session.VPNType, -+ "globalprotect.host_id": session.HostID, -+ "globalprotect.app_version": session.AppVersion, -+ "globalprotect.virtual_ip": session.VirtualIP, -+ "globalprotect.virtual_ipv6": session.VirtualIPv6, -+ "globalprotect.public_ip": session.PublicIP, -+ "globalprotect.public_ipv6": session.PublicIPv6, -+ "globalprotect.tunnel_type": session.TunnelType, -+ "globalprotect.public_connection_ipv6": session.PublicConnectionIPv6, -+ "globalprotect.client_ip": session.ClientIP, -+ "globalprotect.login_time": session.LoginTime, -+ "globalprotect.login_time_utc": session.LoginTimeUTC, -+ "globalprotect.lifetime": session.Lifetime, -+ "globalprotect.request_login": session.RequestLogin, -+ "globalprotect.request_get_config": session.RequestGetConfig, -+ "globalprotect.request_sslvpn_connect": session.RequestSSLVPNConnect, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -+ }, -+ } - - events = append(events, event) - } -diff --git a/x-pack/metricbeat/module/panos/vpn/gp_stats.go b/x-pack/metricbeat/module/panos/vpn/gp_stats.go -index f7177fe300..5907d784f2 100644 ---- a/x-pack/metricbeat/module/panos/vpn/gp_stats.go -+++ b/x-pack/metricbeat/module/panos/vpn/gp_stats.go -@@ -6,6 +6,7 @@ package vpn - - import ( - "encoding/xml" -+ "fmt" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" -@@ -18,45 +19,48 @@ func getGlobalProtectStatsEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error querying GlobalProtect statistics: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error unmarshaling GlobalProtect statistics response: %w", err) - } - - events := formatGPStatsEvents(m, response) - - return events, nil -- - } - - func formatGPStatsEvents(m *MetricSet, response GPStatsResponse) []mb.Event { -+ if len(response.Result.Gateways) == 0 { -+ return nil -+ } -+ - events := make([]mb.Event, 0, len(response.Result.Gateways)) - -- currentTime := time.Now() -+ timestamp := time.Now() - totalCurrent := response.Result.TotalCurrentUsers - totalPrevious := response.Result.TotalPreviousUsers - - for _, gateway := range response.Result.Gateways { -- event := mb.Event{MetricSetFields: mapstr.M{ -- "globalprotect.gateway.name": gateway.Name, -- "globalprotect.gateway.current_users": gateway.CurrentUsers, -- "globalprotect.gateway.previous_users": gateway.PreviousUsers, -- "globalprotect.total_current_users": totalCurrent, -- "globalprotect.total_previous_users": totalPrevious, -- }, -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "globalprotect.gateway.name": gateway.Name, -+ "globalprotect.gateway.current_users": gateway.CurrentUsers, -+ "globalprotect.gateway.previous_users": gateway.PreviousUsers, -+ "globalprotect.total_current_users": totalCurrent, -+ "globalprotect.total_previous_users": totalPrevious, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -- -+ }, -+ } - events = append(events, event) - } - -diff --git a/x-pack/metricbeat/module/panos/vpn/tunnels.go b/x-pack/metricbeat/module/panos/vpn/tunnels.go -index 8dcb13a79e..1d22cc2625 100644 ---- a/x-pack/metricbeat/module/panos/vpn/tunnels.go -+++ b/x-pack/metricbeat/module/panos/vpn/tunnels.go -@@ -6,6 +6,7 @@ package vpn - - import ( - "encoding/xml" -+ "fmt" - "time" - - "github.com/elastic/beats/v7/metricbeat/mb" -@@ -18,59 +19,55 @@ func getIPSecTunnelEvents(m *MetricSet) ([]mb.Event, error) { - - output, err := m.client.Op(query, vsys, nil, nil) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error querying IPSec tunnels: %w", err) - } - - err = xml.Unmarshal(output, &response) - if err != nil { -- m.logger.Error("Error: %s", err) -- return nil, err -+ return nil, fmt.Errorf("error unmarshaling IPSec tunnels response: %w", err) - } - -- events := getEvents(m, response.Result.Entries) -+ events := formatIPSecTunnelEvents(m, response.Result.Entries) - - return events, nil -- - } - --func getEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { -+func formatIPSecTunnelEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { - events := make([]mb.Event, 0, len(entries)) -- -- currentTime := time.Now() -+ timestamp := time.Now() - - for _, entry := range entries { -- event := mb.Event{MetricSetFields: mapstr.M{ -- "ipsec_tunnel.id": entry.ID, -- "ipsec_tunnel.name": entry.Name, -- "ipsec_tunnel.gw": entry.GW, -- "ipsec_tunnel.TSi_ip": entry.TSiIP, -- "ipsec_tunnel.TSi_prefix": entry.TSiPrefix, -- "ipsec_tunnel.TSi_proto": entry.TSiProto, -- "ipsec_tunnel.TSi_port": entry.TSiPort, -- "ipsec_tunnel.TSr_ip": entry.TSrIP, -- "ipsec_tunnel.TSr_prefix": entry.TSrPrefix, -- "ipsec_tunnel.TSr_proto": entry.TSrProto, -- "ipsec_tunnel.TSr_port": entry.TSrPort, -- "ipsec_tunnel.proto": entry.Proto, -- "ipsec_tunnel.mode": entry.Mode, -- "ipsec_tunnel.dh": entry.DH, -- "ipsec_tunnel.enc": entry.Enc, -- "ipsec_tunnel.hash": entry.Hash, -- "ipsec_tunnel.life": entry.Life, -- "ipsec_tunnel.kb": entry.KB, -- }, -+ event := mb.Event{ -+ Timestamp: timestamp, -+ MetricSetFields: mapstr.M{ -+ "ipsec_tunnel.id": entry.ID, -+ "ipsec_tunnel.name": entry.Name, -+ "ipsec_tunnel.gw": entry.GW, -+ "ipsec_tunnel.TSi_ip": entry.TSiIP, -+ "ipsec_tunnel.TSi_prefix": entry.TSiPrefix, -+ "ipsec_tunnel.TSi_proto": entry.TSiProto, -+ "ipsec_tunnel.TSi_port": entry.TSiPort, -+ "ipsec_tunnel.TSr_ip": entry.TSrIP, -+ "ipsec_tunnel.TSr_prefix": entry.TSrPrefix, -+ "ipsec_tunnel.TSr_proto": entry.TSrProto, -+ "ipsec_tunnel.TSr_port": entry.TSrPort, -+ "ipsec_tunnel.proto": entry.Proto, -+ "ipsec_tunnel.mode": entry.Mode, -+ "ipsec_tunnel.dh": entry.DH, -+ "ipsec_tunnel.enc": entry.Enc, -+ "ipsec_tunnel.hash": entry.Hash, -+ "ipsec_tunnel.life": entry.Life, -+ "ipsec_tunnel.kb": entry.KB, -+ }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", -- "@Timestamp": currentTime, -- }} -- -+ }, -+ } - events = append(events, event) - } - - return events -- - } -diff --git a/x-pack/metricbeat/module/panos/vpn/vpn.go b/x-pack/metricbeat/module/panos/vpn/vpn.go -index e3f428bbf5..d7582951c6 100644 ---- a/x-pack/metricbeat/module/panos/vpn/vpn.go -+++ b/x-pack/metricbeat/module/panos/vpn/vpn.go -@@ -6,7 +6,7 @@ package vpn - - import ( - "errors" -- "strings" -+ "fmt" - - "github.com/elastic/beats/v7/libbeat/common/cfgwarn" - "github.com/elastic/beats/v7/metricbeat/mb" -@@ -50,7 +50,6 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - - logger := logp.NewLogger(base.FullyQualifiedName()) - -- //client := &pango.Firewall{Client: pango.Client{Hostname: config.HostIp, ApiKey: config.ApiKey}} - client, err := panos.GetPanosClient(config) - if err != nil { - return nil, err -@@ -68,44 +67,31 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { - // format. It publishes the event which is then forwarded to the output. In case - // of an error set the Error field of mb.Event or simply call report.Error(). - func (m *MetricSet) Fetch(report mb.ReporterV2) error { -- // accumulate errs and report them all at the end so that we don't -- // stop processing events if one of the fetches fails -- var errs []string -- -- gpSessionEvents, err := getGlobalProtectSessionEvents(m) -- if err != nil { -- m.logger.Error("Error get GlobalProtect session events: %s", err) -- errs = append(errs, err.Error()) -- } -- -- for _, event := range gpSessionEvents { -- report.Event(event) -- } -- -- gpStatsEvents, err := getGlobalProtectStatsEvents(m) -- if err != nil { -- m.logger.Error("Error get GlobalProtect stats events: %s", err) -- errs = append(errs, err.Error()) -+ var errs []error -+ -+ eventFetchers := []struct { -+ name string -+ fn func(*MetricSet) ([]mb.Event, error) -+ }{ -+ {"globalprotect session", getGlobalProtectSessionEvents}, -+ {"globalprotect stats", getGlobalProtectStatsEvents}, -+ {"ipsec tunnel", getIPSecTunnelEvents}, - } - -- for _, event := range gpStatsEvents { -- report.Event(event) -- } -- -- ipsecTunnelsEvents, err := getIPSecTunnelEvents(m) -- if err != nil { -- m.logger.Error("Error get IPSec Tunnel events: %s", err) -- errs = append(errs, err.Error()) -- } -- -- for _, event := range ipsecTunnelsEvents { -- report.Event(event) -+ for _, fetcher := range eventFetchers { -+ events, err := fetcher.fn(m) -+ if err != nil { -+ m.logger.Errorf("Error getting %s events: %s", fetcher.name, err) -+ errs = append(errs, err) -+ } else { -+ for _, event := range events { -+ report.Event(event) -+ } -+ } - } - - if len(errs) > 0 { -- return errors.New(strings.Join(errs, "; ")) -- } else { -- return nil -+ return fmt.Errorf("error while fetching vpn metrics: %w", errors.Join(errs...)) - } -- -+ return nil - } From 8e2d8999d81f441c5ec5feca5436cba8117188d7 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Thu, 12 Sep 2024 16:34:41 -0400 Subject: [PATCH 21/32] Changes to: - move tunnels from vpn to interfaces metricset - address PR comments for field names in field.yml - split local/peer addresses into host and port for bgp - handle license expires of "never" --- x-pack/metricbeat/module/panw/config.go | 12 +-- .../module/panw/interfaces/_meta/fields.yml | 84 +++++++++++++++++-- .../module/panw/interfaces/interface_types.go | 33 ++++++++ .../module/panw/interfaces/interfaces.go | 1 + .../panw/{vpn => interfaces}/tunnels.go | 4 +- .../module/panw/routing/_meta/fields.yml | 50 ++++++----- .../module/panw/routing/bgp_peers.go | 23 +++-- .../metricbeat/module/panw/routing/routing.go | 2 +- .../module/panw/system/_meta/fields.yml | 8 +- .../metricbeat/module/panw/system/license.go | 31 +++++-- .../module/panw/vpn/_meta/fields.yml | 72 ---------------- x-pack/metricbeat/module/panw/vpn/vpn.go | 1 - .../metricbeat/module/panw/vpn/vpn_types.go | 33 -------- 13 files changed, 191 insertions(+), 163 deletions(-) rename x-pack/metricbeat/module/panw/{vpn => interfaces}/tunnels.go (97%) diff --git a/x-pack/metricbeat/module/panw/config.go b/x-pack/metricbeat/module/panw/config.go index bf1f859723a..30a14bd12c6 100644 --- a/x-pack/metricbeat/module/panw/config.go +++ b/x-pack/metricbeat/module/panw/config.go @@ -5,8 +5,6 @@ package panw import ( - "errors" - "github.com/elastic/beats/v7/metricbeat/mb" ) @@ -15,10 +13,10 @@ const ( ) type Config struct { - HostIp string `config:"host_ip"` + HostIp string `config:"host_ip" validate:"required"` + ApiKey string `config:"api_key" validate:"required"` Port uint `config:"port"` - ApiKey string `config:"apiKey"` - DebugMode string `config:"apiDebugMode"` + DebugMode string `config:"api_debug_mode"` } func NewConfig(base mb.BaseMetricSet) (*Config, error) { @@ -27,10 +25,6 @@ func NewConfig(base mb.BaseMetricSet) (*Config, error) { return nil, err } - if (config.HostIp == "") || (config.ApiKey == "") { - return nil, errors.New("host_ip and apiKey must be set ") - } - return &config, nil } diff --git a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml index 0f0bd265a94..f46c4751817 100644 --- a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml @@ -82,7 +82,7 @@ - name: logical.addr type: keyword description: > - Used to store aditional static IP addresses + Used to store additional static IP addresses - name: logical.dyn_addr type: keyword description: > @@ -116,10 +116,10 @@ type: keyword description: > HA state of the local device, e.g., "active" or "passive" - - name: ha.local_info.state_duration + - name: ha.local_info.state_duration.sec type: long description: > - Duration in milliseconds of the current state + Duration in seconds of the current state - name: ha.local_info.mgmt_ip type: ip description: > @@ -224,10 +224,10 @@ type: keyword description: > Current operational state of the peer firewall (passive means it is in standby mode and not handling traffic) - - name: ha.peer_info.state_duration + - name: ha.peer_info.state_duration.sec type: long description: > - How long the peer has been in the current state + How long the peer has been in the current state in seconds - name: ha.peer_info.mgmt_ip type: ip description: > @@ -331,4 +331,76 @@ - name: ha.link_monitoring.group.interface.status type: keyword description: > - Status of the interface in the link monitoring group \ No newline at end of file + Status of the interface in the link monitoring group + - name: ipsec_tunnel.id + type: keyword + description: > + ID of the IPsec tunnel + - name: ipsec_tunnel.name + type: keyword + description: > + Name of the IPsec tunnel + - name: ipsec_tunnel.gw + type: keyword + description: > + Gateway of the IPsec tunnel + - name: ipsec_tunnel.TSi_ip + type: ip + description: > + Traffic Selector Initiator IP. This is the local IP (0.0.0.0 means any IP address) + - name: ipsec_tunnel.TSi_prefix + type: keyword + description: > + Network prefix for the TSi IP, 0 means no specific network is defined. + - name: ipsec_tunnel.TSi_proto + type: keyword + description: > + Protocol associated with the TSi (0 means any protocol) + - name: ipsec_tunnel.TSi_port + type: long + description: > + Port number associated with TSi (0 means any port) + - name: ipsec_tunnel.TSr_ip + type: ip + description: > + Traffic Selector Responder IP. + - name: ipsec_tunnel.TSr_prefix + type: keyword + description: > + Network prefix for the TSr IP. Similar to TSi_prefix + - name: ipsec_tunnel.TSr_proto + type: keyword + description: > + TSr protocol of the IPsec tunnel + - name: ipsec_tunnel.TSr_port + type: long + description: > + TSr port of the IPsec tunnel + - name: ipsec_tunnel.proto + type: keyword + description: > + Protocol of the IPsec tunnel + - name: ipsec_tunnel.mode + type: keyword + description: > + This specifies the IPsec mode. e.g., 'tunl' + - name: ipsec_tunnel.dh + type: keyword + description: > + Diffie-Hellman group of the IPsec tunnel + - name: ipsec_tunnel.enc + type: keyword + description: > + Encryption algorithm of the IPsec tunnel + - name: ipsec_tunnel.hash + type: keyword + description: > + Hash algorithm of the IPsec tunnel + - name: ipsec_tunnel.life.sec + type: long + description: > + The lifetime of the IPsec Security Association (SA) in seconds + - name: ipsec_tunnel.kb + type: long + description: > + Traffic volume limit for SA rekeying \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/interfaces/interface_types.go b/x-pack/metricbeat/module/panw/interfaces/interface_types.go index 452702ada7d..b1f3e944562 100644 --- a/x-pack/metricbeat/module/panw/interfaces/interface_types.go +++ b/x-pack/metricbeat/module/panw/interfaces/interface_types.go @@ -214,3 +214,36 @@ type HAPathMonitoring struct { VLAN string `xml:"vlan"` VirtualRouter string `xml:"virtual-router"` } + +// IPSec tunnels + +type TunnelsResponse struct { + Status string `xml:"status,attr"` + Result TunnelsResult `xml:"result"` +} + +type TunnelsResult struct { + Entries []TunnelsEntry `xml:"entries>entry"` + NTun int `xml:"ntun"` +} + +type TunnelsEntry struct { + ID int `xml:"id"` + Name string `xml:"name"` + GW string `xml:"gw"` + TSiIP string `xml:"TSi_ip"` + TSiPrefix int `xml:"TSi_prefix"` + TSiProto int `xml:"TSi_proto"` + TSiPort int `xml:"TSi_port"` + TSrIP string `xml:"TSr_ip"` + TSrPrefix int `xml:"TSr_prefix"` + TSrProto int `xml:"TSr_proto"` + TSrPort int `xml:"TSr_port"` + Proto string `xml:"proto"` + Mode string `xml:"mode"` + DH string `xml:"dh"` + Enc string `xml:"enc"` + Hash string `xml:"hash"` + Life int `xml:"life"` + KB int `xml:"kb"` +} diff --git a/x-pack/metricbeat/module/panw/interfaces/interfaces.go b/x-pack/metricbeat/module/panw/interfaces/interfaces.go index e3fbceaa00b..2f93798f53d 100644 --- a/x-pack/metricbeat/module/panw/interfaces/interfaces.go +++ b/x-pack/metricbeat/module/panw/interfaces/interfaces.go @@ -77,6 +77,7 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { }{ {"ifnet interfaces", getIFNetInterfaceEvents}, {"HA interfaces", getHAInterfaceEvents}, + {"ipsec tunnel", getIPSecTunnelEvents}, } for _, fetcher := range eventFetchers { diff --git a/x-pack/metricbeat/module/panw/vpn/tunnels.go b/x-pack/metricbeat/module/panw/interfaces/tunnels.go similarity index 97% rename from x-pack/metricbeat/module/panw/vpn/tunnels.go rename to x-pack/metricbeat/module/panw/interfaces/tunnels.go index 3ec649b4892..72c01065aff 100644 --- a/x-pack/metricbeat/module/panw/vpn/tunnels.go +++ b/x-pack/metricbeat/module/panw/interfaces/tunnels.go @@ -2,7 +2,7 @@ // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. -package vpn +package interfaces import ( "encoding/xml" @@ -66,7 +66,7 @@ func formatIPSecTunnelEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { "ipsec_tunnel.dh": entry.DH, "ipsec_tunnel.enc": entry.Enc, "ipsec_tunnel.hash": entry.Hash, - "ipsec_tunnel.life": entry.Life, + "ipsec_tunnel.life.sec": entry.Life, "ipsec_tunnel.kb": entry.KB, }, RootFields: mapstr.M{ diff --git a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml index d594612c9c7..4af4dc1dd5e 100644 --- a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml @@ -28,7 +28,7 @@ type: keyword description: > The BGP session status, e.g., "Established" means the session is up and running - - name: bgp.status_duration + - name: bgp.status_duration.sec type: long description: > Time in seconds since the current status was set @@ -43,15 +43,23 @@ - name: bgp.multi_hop_ttl type: long description: > - Time to Live (TTL) value for multi-hop BGP sessions. - - name: bgp.peer_address - type: keyword + Time to Live (TTL) value for multi-hop BGP sessions. Units are the number of hops. + - name: bgp.peer_ip + type: ip description: > - IP address and port of the peer - - name: bgp.local_address - type: keyword + IP address of the peer + - name: bgp.peer_port + type: long + description: > + Port number of the peer + - name: bgp.local_ip + type: ip + description: > + Local ip address used for BGP connection + - name: bgp.local_port + type: long description: > - Local address and port used for BGP connection + Local port number used for BGP connection - name: bgp.reflector_client type: keyword description: > @@ -68,15 +76,15 @@ type: keyword description: > Defines the type of relationship between peers, e.g., "External BGP", "Internal BGP", or "Unspecified" - - name: bgp.connect_retry_interval + - name: bgp.connect_retry_interval.sec type: long description: > The interval (in seconds) between connection retries - - name: bgp.open_delay + - name: bgp.open_delay.sec type: long description: > Delay before sending an Open message (in seconds) - - name: bgp.idle_hold + - name: bgp.idle_hold.sec type: long description: > The idle hold time (in seconds) before retrying a connection after failure @@ -84,39 +92,39 @@ type: long description: > The maximum number of prefixes that can be received from the peer (0 = no limit) - - name: bgp.holdtime + - name: bgp.holdtime.sec type: long description: > Time in seconds that the BGP peer will wait for a keepalive message, negotiated between peers - - name: bgp.holdtime_config + - name: bgp.holdtime_config.sec type: long description: > - Represents the locally configured hold time on this peer - - name: bgp.keepalive + Represents the locally configured hold time on this peer (in seconds) + - name: bgp.keepalive.sec type: long description: > The interval (in seconds) at which BGP keepalive messages are sent, negotiated between peers - - name: bgp.keepalive_config + - name: bgp.keepalive_config.sec type: long description: > The keepalive configured on this peer - - name: bgp.msg_update_in + - name: bgp.msg_update_in.count type: long description: > The number of BGP UPDATE messages received by the router from this peer - - name: bgp.msg_update_out + - name: bgp.msg_update_out.count type: long description: > the number of BGP UPDATE messages sent from the local router to the peer - - name: bgp.msg_total_in + - name: bgp.msg_total_in.count type: long description: > Total of all messages received from the peer - - name: bgp.msg_total_out + - name: bgp.msg_total_out.count type: long description: > Total of all messages sent to the peer - - name: bgp.last_update_age + - name: bgp.last_update_age.sec type: long description: > Time in seconds since the last update message was received from the peer diff --git a/x-pack/metricbeat/module/panw/routing/bgp_peers.go b/x-pack/metricbeat/module/panw/routing/bgp_peers.go index 674bb96a72f..602497be8af 100644 --- a/x-pack/metricbeat/module/panw/routing/bgp_peers.go +++ b/x-pack/metricbeat/module/panw/routing/bgp_peers.go @@ -6,6 +6,7 @@ package routing import ( "encoding/xml" + "net" "time" "github.com/elastic/beats/v7/metricbeat/mb" @@ -23,12 +24,6 @@ func getBGPEvents(m *MetricSet) ([]mb.Event, error) { bgpLogger = m.logger var response BGPResponse - // Initialize the client - // if err := m.client.Initialize(); err != nil { - // log.Error("Failed to initialize client: %s", err) - // return err - // } - output, err := m.client.Op(bgpPeersQuery, panw.Vsys, nil, nil) if err != nil { m.logger.Error("Error calling API: %s", err) @@ -81,6 +76,16 @@ func formatBGPEvents(m *MetricSet, entries []BGPEntry) []mb.Event { for _, entry := range entries { booleanFields := convertEntryBooleanFields(entry) + peer_ip, peer_port, err := net.SplitHostPort(entry.PeerAddress) + if err != nil { + bgpLogger.Warnf("Error splitting peer address (%s): %v", entry.PeerAddress, err) + peer_ip = entry.PeerAddress + } + local_ip, local_port, err := net.SplitHostPort(entry.LocalAddress) + if err != nil { + bgpLogger.Warnf("Error splitting local address (%s): %v", entry.LocalAddress, err) + local_ip = entry.LocalAddress + } event := mb.Event{ Timestamp: timestamp, @@ -95,8 +100,10 @@ func formatBGPEvents(m *MetricSet, entries []BGPEntry) []mb.Event { "bgp.password_set": booleanFields["bgp.password_set"], "bgp.passive": booleanFields["bgp.passive"], "bgp.multi_hop_ttl": entry.MultiHopTTL, - "bgp.peer_address": entry.PeerAddress, - "bgp.local_address": entry.LocalAddress, + "bgp.peer_ip": peer_ip, + "bgp.peer_port": peer_port, + "bgp.local_ip": local_ip, + "bgp.local_port": local_port, "bgp.reflector_client": entry.ReflectorClient, "bgp.same_confederation": booleanFields["bgp.same_confederation"], "bgp.aggregate_confed_as": booleanFields["bgp.aggregate_confed_as"], diff --git a/x-pack/metricbeat/module/panw/routing/routing.go b/x-pack/metricbeat/module/panw/routing/routing.go index 79a9a685177..ca762c25fef 100644 --- a/x-pack/metricbeat/module/panw/routing/routing.go +++ b/x-pack/metricbeat/module/panw/routing/routing.go @@ -90,7 +90,7 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { } if len(errs) > 0 { - return fmt.Errorf("error while fetching vpn metrics: %w", errors.Join(errs...)) + return fmt.Errorf("error while fetching routing metrics: %w", errors.Join(errs...)) } return nil diff --git a/x-pack/metricbeat/module/panw/system/_meta/fields.yml b/x-pack/metricbeat/module/panw/system/_meta/fields.yml index 385c5ffe99a..20f07ed3c84 100644 --- a/x-pack/metricbeat/module/panw/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/system/_meta/fields.yml @@ -133,9 +133,13 @@ description: > Date the license was issued - name: license.expires - type: keyword + type: date + description: > + Date the license expires - not set if license never expires + - nake: never_expires + type: boolean description: > - Date the license expires, but this is a keyword because value might be "never" + Indicates if the license never expires - name: license.expired type: boolean description: > diff --git a/x-pack/metricbeat/module/panw/system/license.go b/x-pack/metricbeat/module/panw/system/license.go index 1e2741c9431..6e2fc38860e 100644 --- a/x-pack/metricbeat/module/panw/system/license.go +++ b/x-pack/metricbeat/module/panw/system/license.go @@ -7,6 +7,7 @@ package system import ( "encoding/xml" "fmt" + "strings" "time" "github.com/elastic/beats/v7/metricbeat/mb" @@ -54,23 +55,33 @@ func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { // // March 20, 2024 - // May 27, 2025 + // May 27, 2025 or Never // issued, err := time.Parse("January 2, 2006", license.Issued) if err != nil { m.logger.Warn("Failed to parse issued date %s: %s", license.Issued, err) } + never_expires := false + expires, err := time.Parse("January 2, 2006", license.Expires) + // The value of license.Expires is "never" when the license never expires + if err != nil { + if strings.ToLower(license.Expires) == "never" { + never_expires = true + } else { + m.logger.Warn("Failed to parse expires date %s: %s", license.Expires, err) + } + } event := mb.Event{ Timestamp: timestamp, MetricSetFields: mapstr.M{ - "license.feature": license.Feature, - "license.description": license.Description, - "license.serial": license.Serial, - "license.issued": issued.Format(time.RFC3339), - "license.expires": license.Expires, - "license.expired": expired, - "license.auth_code": license.AuthCode, + "license.feature": license.Feature, + "license.description": license.Description, + "license.serial": license.Serial, + "license.issued": issued.Format(time.RFC3339), + "license.never_expires": never_expires, + "license.expired": expired, + "license.auth_code": license.AuthCode, }, RootFields: mapstr.M{ "observer.ip": m.config.HostIp, @@ -79,6 +90,10 @@ func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { "observer.type": "firewall", }, } + // only set the expires field if the license expires + if !never_expires { + event.MetricSetFields["license.expires"] = expires.Format(time.RFC3339) + } events = append(events, event) } diff --git a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml index 73cf15a7f71..dfd495bd13f 100644 --- a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml @@ -120,75 +120,3 @@ type: long description: > Total previous number of users connected to GlobalProtect - - name: ipsec_tunnel.id - type: keyword - description: > - ID of the IPsec tunnel - - name: ipsec_tunnel.name - type: keyword - description: > - Name of the IPsec tunnel - - name: ipsec_tunnel.gw - type: keyword - description: > - Gateway of the IPsec tunnel - - name: ipsec_tunnel.TSi_ip - type: ip - description: > - Traffic Selector Initiator IP. This is the local IP (0.0.0.0 means any IP address) - - name: ipsec_tunnel.TSi_prefix - type: keyword - description: > - Network prefix for the TSi IP, 0 means no specific network is defined. - - name: ipsec_tunnel.TSi_proto - type: keyword - description: > - Protocol associated with the TSi (0 means any protocol) - - name: ipsec_tunnel.TSi_port - type: long - description: > - Port number associated with TSi (0 means any port) - - name: ipsec_tunnel.TSr_ip - type: ip - description: > - Traffic Selector Responder IP. - - name: ipsec_tunnel.TSr_prefix - type: keyword - description: > - Network prefix for the TSr IP. Similar to TSi_prefix - - name: ipsec_tunnel.TSr_proto - type: keyword - description: > - TSr protocol of the IPsec tunnel - - name: ipsec_tunnel.TSr_port - type: long - description: > - TSr port of the IPsec tunnel - - name: ipsec_tunnel.proto - type: keyword - description: > - Protocol of the IPsec tunnel - - name: ipsec_tunnel.mode - type: keyword - description: > - This specifies the IPsec mode. e.g., 'tunl' - - name: ipsec_tunnel.dh - type: keyword - description: > - Diffie-Hellman group of the IPsec tunnel - - name: ipsec_tunnel.enc - type: keyword - description: > - Encryption algorithm of the IPsec tunnel - - name: ipsec_tunnel.hash - type: keyword - description: > - Hash algorithm of the IPsec tunnel - - name: ipsec_tunnel.life - type: long - description: > - The lifetime of the IPsec Security Association (SA) in seconds - - name: ipsec_tunnel.kb - type: long - description: > - Traffic volume limit for SA rekeying \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/vpn/vpn.go b/x-pack/metricbeat/module/panw/vpn/vpn.go index d7d838bcc01..4a1f304b631 100644 --- a/x-pack/metricbeat/module/panw/vpn/vpn.go +++ b/x-pack/metricbeat/module/panw/vpn/vpn.go @@ -78,7 +78,6 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { }{ {"globalprotect session", getGlobalProtectSessionEvents}, {"globalprotect stats", getGlobalProtectStatsEvents}, - {"ipsec tunnel", getIPSecTunnelEvents}, } for _, fetcher := range eventFetchers { diff --git a/x-pack/metricbeat/module/panw/vpn/vpn_types.go b/x-pack/metricbeat/module/panw/vpn/vpn_types.go index 236a291a908..216a6b77509 100644 --- a/x-pack/metricbeat/module/panw/vpn/vpn_types.go +++ b/x-pack/metricbeat/module/panw/vpn/vpn_types.go @@ -59,36 +59,3 @@ type GPGateway struct { CurrentUsers int `xml:"CurrentUsers"` PreviousUsers int `xml:"PreviousUsers"` } - -// IPSec tunnels - -type TunnelsResponse struct { - Status string `xml:"status,attr"` - Result TunnelsResult `xml:"result"` -} - -type TunnelsResult struct { - Entries []TunnelsEntry `xml:"entries>entry"` - NTun int `xml:"ntun"` -} - -type TunnelsEntry struct { - ID int `xml:"id"` - Name string `xml:"name"` - GW string `xml:"gw"` - TSiIP string `xml:"TSi_ip"` - TSiPrefix int `xml:"TSi_prefix"` - TSiProto int `xml:"TSi_proto"` - TSiPort int `xml:"TSi_port"` - TSrIP string `xml:"TSr_ip"` - TSrPrefix int `xml:"TSr_prefix"` - TSrProto int `xml:"TSr_proto"` - TSrPort int `xml:"TSr_port"` - Proto string `xml:"proto"` - Mode string `xml:"mode"` - DH string `xml:"dh"` - Enc string `xml:"enc"` - Hash string `xml:"hash"` - Life int `xml:"life"` - KB int `xml:"kb"` -} From 1e738858ee4eb12867b40a3237085528a981bbfd Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Mon, 16 Sep 2024 16:34:51 -0400 Subject: [PATCH 22/32] Fixes for PR comments --- .../module/panw/interfaces/ha_interfaces.go | 30 ++++++++-------- .../panw/interfaces/ifnet_interfaces.go | 27 +++++++------- .../module/panw/interfaces/tunnels.go | 11 +++--- .../module/panw/routing/_meta/fields.yml | 2 +- .../module/panw/routing/bgp_peers.go | 11 +++--- .../module/panw/system/_meta/fields.yml | 15 ++++---- .../module/panw/system/certificates.go | 10 ++---- x-pack/metricbeat/module/panw/system/fans.go | 10 ++---- .../module/panw/system/filesystem.go | 24 +++++-------- .../metricbeat/module/panw/system/license.go | 35 +++++++++---------- x-pack/metricbeat/module/panw/system/power.go | 10 ++---- .../module/panw/system/resources.go | 19 ++++++---- .../metricbeat/module/panw/system/system.go | 2 +- .../metricbeat/module/panw/system/thermal.go | 17 +++++---- x-pack/metricbeat/module/panw/util.go | 11 ++++++ .../module/panw/vpn/_meta/fields.yml | 4 +-- .../metricbeat/module/panw/vpn/gp_sessions.go | 13 +++---- x-pack/metricbeat/module/panw/vpn/gp_stats.go | 11 +++--- x-pack/metricbeat/modules.d/panw.yml.disabled | 4 +-- 19 files changed, 122 insertions(+), 144 deletions(-) diff --git a/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go b/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go index 42f13ecd3f6..7228eca2955 100644 --- a/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go +++ b/x-pack/metricbeat/module/panw/interfaces/ha_interfaces.go @@ -25,13 +25,13 @@ func getHAInterfaceEvents(m *MetricSet) ([]mb.Event, error) { output, err := m.client.Op(haInterfaceQuery, panw.Vsys, nil, nil) if err != nil { - m.logger.Error("Error: %s", err) + haLogger.Error("Error: %s", err) return nil, err } err = xml.Unmarshal(output, &response) if err != nil { - m.logger.Error("Error: %s", err) + haLogger.Errorw("Failed to unmarshal interface response", "error", err, "query", haInterfaceQuery) return nil, err } @@ -56,7 +56,9 @@ func formatHAInterfaceEvents(m *MetricSet, input HAResult) []mb.Event { func makeGroupEvent(m *MetricSet, input HAResult) *mb.Event { group := input.Group - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) + linkMonitoringEnabled, err := panw.StringToBool(group.LinkMonitoring.Enabled) if err != nil { haLogger.Warn("Error converting LinkMonitoring.Enabled to boolean: %s", err) @@ -128,12 +130,7 @@ func makeGroupEvent(m *MetricSet, input HAResult) *mb.Event { "ha.peer_info.conn_ha1_backup.description": group.PeerInfo.ConnHA1Backup.Desc, "ha.link_monitoring.enabled": linkMonitoringEnabled, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }, + RootFields: rootFields, } return &event @@ -145,9 +142,15 @@ func makeLinkMonitoringEvents(m *MetricSet, links HALinkMonitoring) []mb.Event { } events := make([]mb.Event, 0, len(links.Groups)) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) + var event mb.Event for _, group := range links.Groups { + if group.Interface == nil { + haLogger.Warn("No interface entries found in link monitoring group: %s", group.Name) + continue + } for _, interface_entry := range group.Interface { linkEnabled, err := panw.StringToBool(links.Enabled) if err != nil { @@ -169,12 +172,7 @@ func makeLinkMonitoringEvents(m *MetricSet, links HALinkMonitoring) []mb.Event { "ha.link_monitoring.group.interface.name": interface_entry.Name, "ha.link_monitoring.group.interface.status": interface_entry.Status, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }, + RootFields: rootFields, } } diff --git a/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go b/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go index 7edd1e3b4a1..a94d1522b31 100644 --- a/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go +++ b/x-pack/metricbeat/module/panw/interfaces/ifnet_interfaces.go @@ -50,15 +50,21 @@ func getIFNetInterfaceEvents(m *MetricSet) ([]mb.Event, error) { func formatIFInterfaceEvents(m *MetricSet, input InterfaceResult) []mb.Event { events := make([]mb.Event, 0, len(input.HW.Entries)+len(input.Ifnet.Entries)) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) // First process the phyiscal interfaces for _, entry := range input.HW.Entries { - iftype := interfaceTypes[entry.Type] + iftype, ok := interfaceTypes[entry.Type] + + if !ok { + m.logger.Warnw("Unknown interface type", "type", entry.Type) + iftype = "Unknown" + } var members []string // If this is an aggregate interface, populate the members - if entry.Type == 1 { + if entry.Type == 1 && len(entry.AEMember.Members) != 0 { members = entry.AEMember.Members } @@ -76,12 +82,7 @@ func formatIFInterfaceEvents(m *MetricSet, input InterfaceResult) []mb.Event { "physical.full_state": entry.ST, "physical.ae_member": members, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }, + RootFields: rootFields, } events = append(events, event) @@ -103,12 +104,8 @@ func formatIFInterfaceEvents(m *MetricSet, input InterfaceResult) []mb.Event { "logical.dyn_addr": entry.DynAddr, "logical.addr6": entry.Addr6, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }} + RootFields: rootFields, + } events = append(events, event) diff --git a/x-pack/metricbeat/module/panw/interfaces/tunnels.go b/x-pack/metricbeat/module/panw/interfaces/tunnels.go index 72c01065aff..df01bec93dd 100644 --- a/x-pack/metricbeat/module/panw/interfaces/tunnels.go +++ b/x-pack/metricbeat/module/panw/interfaces/tunnels.go @@ -44,7 +44,8 @@ func formatIPSecTunnelEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { } events := make([]mb.Event, 0, len(entries)) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) for _, entry := range entries { event := mb.Event{ @@ -69,12 +70,8 @@ func formatIPSecTunnelEvents(m *MetricSet, entries []TunnelsEntry) []mb.Event { "ipsec_tunnel.life.sec": entry.Life, "ipsec_tunnel.kb": entry.KB, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }} + RootFields: rootFields, + } events = append(events, event) } diff --git a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml index 4af4dc1dd5e..06eaa7cfaec 100644 --- a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml @@ -63,7 +63,7 @@ - name: bgp.reflector_client type: keyword description: > - Indicates if the BGP peer is a route reflector client + Specifies the BGP peer relationship to route reflectors, e.g. "client", "not-client", "meshed-client" - name: bgp.same_confederation type: boolean description: > diff --git a/x-pack/metricbeat/module/panw/routing/bgp_peers.go b/x-pack/metricbeat/module/panw/routing/bgp_peers.go index 602497be8af..a99ec08c6d7 100644 --- a/x-pack/metricbeat/module/panw/routing/bgp_peers.go +++ b/x-pack/metricbeat/module/panw/routing/bgp_peers.go @@ -72,7 +72,8 @@ func convertEntryBooleanFields(entry BGPEntry) map[string]bool { func formatBGPEvents(m *MetricSet, entries []BGPEntry) []mb.Event { events := make([]mb.Event, 0, len(entries)) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) for _, entry := range entries { booleanFields := convertEntryBooleanFields(entry) @@ -129,12 +130,8 @@ func formatBGPEvents(m *MetricSet, entries []BGPEntry) []mb.Event { "bgp.nexthop_thirdparty": booleanFields["bgp.nexthop_thirdparty"], "bgp.nexthop_peer": booleanFields["bgp.nexthop_peer"], }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }} + RootFields: rootFields, + } events = append(events, event) } diff --git a/x-pack/metricbeat/module/panw/system/_meta/fields.yml b/x-pack/metricbeat/module/panw/system/_meta/fields.yml index 20f07ed3c84..9bb10e6f008 100644 --- a/x-pack/metricbeat/module/panw/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/system/_meta/fields.yml @@ -15,7 +15,7 @@ - name: uptime.minutes type: integer description: > - Minutes component of uptime + Minutes component of uptime - name: user_count type: long description: > @@ -136,7 +136,7 @@ type: date description: > Date the license expires - not set if license never expires - - nake: never_expires + - name: license.never_expires type: boolean description: > Indicates if the license never expires @@ -156,12 +156,12 @@ type: float format: bytes description: > - Total size of the filesystem + Total size of the filesystem - name: filesystem.used type: float format: bytes description: > - Amount used on the filesystem + Amount used on the filesystem - name: filesystem.available type: float format: bytes @@ -221,7 +221,7 @@ description: > Maximum temperature field - name: power.slot_number - type: keyword + type: integer description: > Slot number field - name: power.description @@ -235,7 +235,7 @@ - name: power.volts type: float description: > - Current Volts + Current Volts - name: power.minimum_volts type: float description: > @@ -243,7 +243,7 @@ - name: power.maximum_volts type: float description: > - Maximum volts recorded + Maximum volts recorded - name: certificate.issuer type: keyword description: > @@ -294,5 +294,4 @@ description: > db_status field - diff --git a/x-pack/metricbeat/module/panw/system/certificates.go b/x-pack/metricbeat/module/panw/system/certificates.go index 1e82b3beedf..302225847b6 100644 --- a/x-pack/metricbeat/module/panw/system/certificates.go +++ b/x-pack/metricbeat/module/panw/system/certificates.go @@ -46,7 +46,8 @@ func getCertificateEvents(m *MetricSet) ([]mb.Event, error) { } func formatCertificateEvents(m *MetricSet, input string) ([]mb.Event, error) { - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) certificates, err := parseCertificates(input) if err != nil { @@ -71,12 +72,7 @@ func formatCertificateEvents(m *MetricSet, input string) ([]mb.Event, error) { "certificate.db_name": certificate.DBName, "certificate.db_status": certificate.DBStatus, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }, + RootFields: rootFields, } events = append(events, event) diff --git a/x-pack/metricbeat/module/panw/system/fans.go b/x-pack/metricbeat/module/panw/system/fans.go index beec38f7c35..e2c305c4524 100644 --- a/x-pack/metricbeat/module/panw/system/fans.go +++ b/x-pack/metricbeat/module/panw/system/fans.go @@ -39,7 +39,8 @@ func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { } events := make([]mb.Event, 0) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) for _, slot := range response.Result.Fan.Slots { for _, entry := range slot.Entries { @@ -57,12 +58,7 @@ func formatFanEvents(m *MetricSet, response *FanResponse) []mb.Event { "fan.rpm": entry.RPMs, "fan.min_rpm": entry.Min, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }, + RootFields: rootFields, } events = append(events, event) } diff --git a/x-pack/metricbeat/module/panw/system/filesystem.go b/x-pack/metricbeat/module/panw/system/filesystem.go index 16cc234c8dc..205fed3f6c0 100644 --- a/x-pack/metricbeat/module/panw/system/filesystem.go +++ b/x-pack/metricbeat/module/panw/system/filesystem.go @@ -56,7 +56,7 @@ func getFilesystems(input string) []Filesystem { filesystemLogger.Debugf("getFilesystems input:\n %s", input) lines := strings.Split(input, "\n") - filesystems := make([]Filesystem, 0) + filesystems := make([]Filesystem, 0, len(lines)-1) // Skip the first line which is the header: // @@ -112,14 +112,11 @@ func convertToBytes(field string, value string) float64 { return result * MBytes case "g": return result * GBytes + case "": + return result default: - // Handle values without units - if units == "" { - return result - } else { - filesystemLogger.Warnf("Unhandled units for field %s, value %s: %s", field, value, units) - return result - } + filesystemLogger.Warnf("Unhandled units for field %s, value %s: %s", field, value, units) + return result } } @@ -130,7 +127,9 @@ func formatFilesystemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { } events := make([]mb.Event, 0, len(filesystems)) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) + for _, filesystem := range filesystems { used, err := strconv.ParseInt(filesystem.UsePerc[:len(filesystem.UsePerc)-1], 10, 64) if err != nil { @@ -147,12 +146,7 @@ func formatFilesystemEvents(m *MetricSet, filesystems []Filesystem) []mb.Event { "filesystem.use_percent": used, "filesystem.mounted": filesystem.Mounted, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }, + RootFields: rootFields, } events = append(events, event) diff --git a/x-pack/metricbeat/module/panw/system/license.go b/x-pack/metricbeat/module/panw/system/license.go index 6e2fc38860e..ee2df32c30d 100644 --- a/x-pack/metricbeat/module/panw/system/license.go +++ b/x-pack/metricbeat/module/panw/system/license.go @@ -15,7 +15,10 @@ import ( "github.com/elastic/elastic-agent-libs/mapstr" ) -const licenseQuery = "" +const ( + licenseQuery = "" + panwDateFormat = "January 2, 2006" +) func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { @@ -27,7 +30,7 @@ func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { } if len(output) == 0 { - return nil, fmt.Errorf("empty response from PanOS") + return nil, fmt.Errorf("empty response from PanOS for license query") } err = xml.Unmarshal(output, &response) @@ -37,7 +40,7 @@ func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { if len(response.Result.Licenses) == 0 { m.logger.Warn("No licenses found in the response") - return nil, nil + return []mb.Event{}, nil } return formatLicenseEvents(m, response.Result.Licenses), nil @@ -45,7 +48,8 @@ func getLicenseEvents(m *MetricSet) ([]mb.Event, error) { func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { events := make([]mb.Event, 0, len(licenses)) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) for _, license := range licenses { expired, err := panw.StringToBool(license.Expired) @@ -57,18 +61,18 @@ func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { // March 20, 2024 // May 27, 2025 or Never // - issued, err := time.Parse("January 2, 2006", license.Issued) + issued, err := time.Parse(panwDateFormat, license.Issued) if err != nil { - m.logger.Warn("Failed to parse issued date %s: %s", license.Issued, err) + m.logger.Warn("Failed to parse license issued date %s: %s", license.Issued, err) } - never_expires := false - expires, err := time.Parse("January 2, 2006", license.Expires) + neverExpires := false + expires, err := time.Parse(panwDateFormat, license.Expires) // The value of license.Expires is "never" when the license never expires if err != nil { if strings.ToLower(license.Expires) == "never" { - never_expires = true + neverExpires = true } else { - m.logger.Warn("Failed to parse expires date %s: %s", license.Expires, err) + m.logger.Warn("Failed to parse license expire date %s: %s", license.Expires, err) } } @@ -79,19 +83,14 @@ func formatLicenseEvents(m *MetricSet, licenses []License) []mb.Event { "license.description": license.Description, "license.serial": license.Serial, "license.issued": issued.Format(time.RFC3339), - "license.never_expires": never_expires, + "license.never_expires": neverExpires, "license.expired": expired, "license.auth_code": license.AuthCode, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }, + RootFields: rootFields, } // only set the expires field if the license expires - if !never_expires { + if !neverExpires { event.MetricSetFields["license.expires"] = expires.Format(time.RFC3339) } diff --git a/x-pack/metricbeat/module/panw/system/power.go b/x-pack/metricbeat/module/panw/system/power.go index b0b7370b48a..50b89cf6ff0 100644 --- a/x-pack/metricbeat/module/panw/system/power.go +++ b/x-pack/metricbeat/module/panw/system/power.go @@ -43,7 +43,8 @@ func getPowerEvents(m *MetricSet) ([]mb.Event, error) { func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { events := make([]mb.Event, 0) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) for _, slot := range response.Result.Power.Slots { for _, entry := range slot.Entries { @@ -58,12 +59,7 @@ func formatPowerEvents(m *MetricSet, response *PowerResponse) []mb.Event { "power.minimum_volts": entry.MinimumVolts, "power.maximum_volts": entry.MaximumVolts, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }, + RootFields: rootFields, } events = append(events, event) } diff --git a/x-pack/metricbeat/module/panw/system/resources.go b/x-pack/metricbeat/module/panw/system/resources.go index 6c889d3fa2c..51c595b1fe0 100644 --- a/x-pack/metricbeat/module/panw/system/resources.go +++ b/x-pack/metricbeat/module/panw/system/resources.go @@ -68,7 +68,8 @@ MiB Swap: 5961.0 total, 4403.5 free, 1557.6 used. 1530.0 avail Mem 2 20 0 0 0 0 S 0.0 0.0 0:00.83 kthreadd */ func formatResourceEvents(m *MetricSet, input string) []mb.Event { - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) events := make([]mb.Event, 0) // We only need the top 5 lines @@ -125,12 +126,7 @@ func formatResourceEvents(m *MetricSet, input string) []mb.Event { "available": swapInfo.Available, }, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }, + RootFields: rootFields, } events = append(events, event) @@ -270,6 +266,10 @@ func parseMemoryInfo(line string) MemoryInfo { //MiB Mem : 5026.9 total, 414.2 free, 2541.5 used, 2071.1 buff/cache re := regexp.MustCompile(`(\d+\.\d+)\s+total,\s+(\d+\.\d+)\s+free,\s+(\d+\.\d+)\s+used,\s+(\d+\.\d+)\s+buff/cache`) matches := re.FindStringSubmatch(line) + if matches == nil { + resourcesLogger.Errorf("Failed to parse memory info: %s", line) + return MemoryInfo{} + } total := parseFloat("total", matches[1]) free := parseFloat("free", matches[2]) @@ -290,6 +290,11 @@ func parseSwapInfo(line string) SwapInfo { re := regexp.MustCompile(`(\d+\.\d+)\s+total,\s+(\d+\.\d+)\s+free,\s+(\d+\.\d+)\s+used[,\.].\s+(\d+\.\d+)\s+avail Mem`) matches := re.FindStringSubmatch(line) + if matches == nil { + resourcesLogger.Errorf("Failed to parse swap info: %s", line) + return SwapInfo{} + } + total := parseFloat("total", matches[1]) free := parseFloat("free", matches[2]) used := parseFloat("used", matches[3]) diff --git a/x-pack/metricbeat/module/panw/system/system.go b/x-pack/metricbeat/module/panw/system/system.go index 6458ac7edef..085af03d82e 100644 --- a/x-pack/metricbeat/module/panw/system/system.go +++ b/x-pack/metricbeat/module/panw/system/system.go @@ -98,7 +98,7 @@ func (m *MetricSet) Fetch(report mb.ReporterV2) error { } if len(errs) > 0 { - return fmt.Errorf("error while fetching vpn metrics: %w", errors.Join(errs...)) + return fmt.Errorf("error while fetching system metrics: %w", errors.Join(errs...)) } return nil diff --git a/x-pack/metricbeat/module/panw/system/thermal.go b/x-pack/metricbeat/module/panw/system/thermal.go index 161b72c0a2d..7f74372eb25 100644 --- a/x-pack/metricbeat/module/panw/system/thermal.go +++ b/x-pack/metricbeat/module/panw/system/thermal.go @@ -42,7 +42,9 @@ func formatThermalEvents(m *MetricSet, response *ThermalResponse) []mb.Event { } events := make([]mb.Event, 0, len(response.Result.Thermal.Slots)) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) + var event mb.Event for _, slot := range response.Result.Thermal.Slots { @@ -62,15 +64,12 @@ func formatThermalEvents(m *MetricSet, response *ThermalResponse) []mb.Event { "thermal.minimum_temp": entry.MinimumTemp, "thermal.maximum_temp": entry.MaximumTemp, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }} - } + RootFields: rootFields, + } - events = append(events, event) + events = append(events, event) + + } } return events diff --git a/x-pack/metricbeat/module/panw/util.go b/x-pack/metricbeat/module/panw/util.go index a160d0d1107..7ecb31fc0f1 100644 --- a/x-pack/metricbeat/module/panw/util.go +++ b/x-pack/metricbeat/module/panw/util.go @@ -3,6 +3,8 @@ package panw import ( "fmt" "strings" + + "github.com/elastic/elastic-agent-libs/mapstr" ) func StringToBool(s string) (bool, error) { @@ -21,3 +23,12 @@ func StringToBool(s string) (bool, error) { // Default to false return false, fmt.Errorf("invalid value: %s", s) } + +func MakeRootFields(HostIp string) mapstr.M { + return mapstr.M{ + "observer.ip": HostIp, + "host.ip": HostIp, + "observer.vendor": "Palo Alto", + "observer.type": "firewall", + } +} diff --git a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml index dfd495bd13f..1a2e9e9eac9 100644 --- a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml @@ -115,8 +115,8 @@ - name: globalprotect.total_current_users type: long description: > - Total current number of users connected to GlobalProtect + Total current number of users connected to GlobalProtect gateway - name: globalprotect.total_previous_users type: long description: > - Total previous number of users connected to GlobalProtect + Total previous number of users connected to GlobalProtect gateway diff --git a/x-pack/metricbeat/module/panw/vpn/gp_sessions.go b/x-pack/metricbeat/module/panw/vpn/gp_sessions.go index 0037051740f..a82924f8a9c 100644 --- a/x-pack/metricbeat/module/panw/vpn/gp_sessions.go +++ b/x-pack/metricbeat/module/panw/vpn/gp_sessions.go @@ -38,12 +38,13 @@ func getGlobalProtectSessionEvents(m *MetricSet) ([]mb.Event, error) { } func formatGPSessionEvents(m *MetricSet, sessions []GPSession) []mb.Event { - if sessions == nil { + if len(sessions) == 0 { return nil } events := make([]mb.Event, 0, len(sessions)) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) for _, session := range sessions { isLocal, err := panw.StringToBool(session.IsLocal) @@ -78,12 +79,8 @@ func formatGPSessionEvents(m *MetricSet, sessions []GPSession) []mb.Event { "globalprotect.session.request_get_config": session.RequestGetConfig, "globalprotect.session.request_sslvpn_connect": session.RequestSSLVPNConnect, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }} + RootFields: rootFields, + } events = append(events, event) } diff --git a/x-pack/metricbeat/module/panw/vpn/gp_stats.go b/x-pack/metricbeat/module/panw/vpn/gp_stats.go index 5a6c3e02dad..10b6a0cd729 100644 --- a/x-pack/metricbeat/module/panw/vpn/gp_stats.go +++ b/x-pack/metricbeat/module/panw/vpn/gp_stats.go @@ -45,7 +45,8 @@ func formatGPStatsEvents(m *MetricSet, response GPStatsResponse) []mb.Event { } events := make([]mb.Event, 0, len(response.Result.Gateways)) - timestamp := time.Now() + timestamp := time.Now().UTC() + rootFields := panw.MakeRootFields(m.config.HostIp) totalCurrent := response.Result.TotalCurrentUsers totalPrevious := response.Result.TotalPreviousUsers @@ -60,12 +61,8 @@ func formatGPStatsEvents(m *MetricSet, response GPStatsResponse) []mb.Event { "globalprotect.total_current_users": totalCurrent, "globalprotect.total_previous_users": totalPrevious, }, - RootFields: mapstr.M{ - "observer.ip": m.config.HostIp, - "host.ip": m.config.HostIp, - "observer.vendor": "Palo Alto", - "observer.type": "firewall", - }} + RootFields: rootFields, + } events = append(events, event) } diff --git a/x-pack/metricbeat/modules.d/panw.yml.disabled b/x-pack/metricbeat/modules.d/panw.yml.disabled index 7ba4805c449..74ffb4fc5fe 100644 --- a/x-pack/metricbeat/modules.d/panw.yml.disabled +++ b/x-pack/metricbeat/modules.d/panw.yml.disabled @@ -12,7 +12,7 @@ period: 10s host_ip: "127.0.0.1" port: - apiKey: "" - apiDebugMode: false + api_key: "" + api_debug_mode: false From 213f4175c3552d419aa55cfceb3cdb41a3f2144f Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Mon, 16 Sep 2024 18:19:42 -0400 Subject: [PATCH 23/32] add license header --- x-pack/metricbeat/module/panw/util.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/metricbeat/module/panw/util.go b/x-pack/metricbeat/module/panw/util.go index 7ecb31fc0f1..a1da2b51590 100644 --- a/x-pack/metricbeat/module/panw/util.go +++ b/x-pack/metricbeat/module/panw/util.go @@ -1,3 +1,7 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + package panw import ( From 7bb44ace7b00f177aff2b0b141ddf5a5ba9c73e3 Mon Sep 17 00:00:00 2001 From: dparkerelastic Date: Mon, 16 Sep 2024 18:22:08 -0400 Subject: [PATCH 24/32] add pango package --- go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/go.mod b/go.mod index a47bf7ec154..129bdcb3233 100644 --- a/go.mod +++ b/go.mod @@ -388,6 +388,7 @@ require ( require ( cloud.google.com/go/storage v1.43.0 + github.com/PaloAltoNetworks/pango v0.10.2 github.com/dlclark/regexp2 v1.4.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/moby/term v0.5.0 // indirect From 615c2b5c7aed17a3514da22d165b65638d0d1dac Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Tue, 17 Sep 2024 15:00:13 +0530 Subject: [PATCH 25/32] mage check && mage update --- go.sum | 2 ++ x-pack/metricbeat/module/panw/fields.go | 2 +- x-pack/metricbeat/modules.d/panw.yml.disabled | 13 ++----------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/go.sum b/go.sum index ec32ee823dd..d9ce04d812a 100644 --- a/go.sum +++ b/go.sum @@ -215,6 +215,8 @@ github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbV github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= github.com/PaesslerAG/jsonpath v0.1.1 h1:c1/AToHQMVsduPAa4Vh6xp2U0evy4t8SWp8imEsylIk= github.com/PaesslerAG/jsonpath v0.1.1/go.mod h1:lVboNxFGal/VwW6d9JzIy56bUsYAP6tH/x80vjnCseY= +github.com/PaloAltoNetworks/pango v0.10.2 h1:Tjn6vIzzAq6Dd7N0mDuiP8w8pz8k5W9zz/TTSUQCsQY= +github.com/PaloAltoNetworks/pango v0.10.2/go.mod h1:GztcRnVLur7G+VFG7Z5ZKNFgScLtsycwPMp1qVebE5g= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= diff --git a/x-pack/metricbeat/module/panw/fields.go b/x-pack/metricbeat/module/panw/fields.go index d8450a6f61f..b3fc09aa118 100644 --- a/x-pack/metricbeat/module/panw/fields.go +++ b/x-pack/metricbeat/module/panw/fields.go @@ -19,5 +19,5 @@ func init() { // AssetPanw returns asset data. // This is the base64 encoded zlib format compressed contents of module/panw. func AssetPanw() string { - return "eJzMnV9v3DiSwN/zKQq+h3UAxxM7yAIxcAf0xjNjA06mETuzh3sR2FKpxbNE6kiqnZ5Pf+Af/W2ppZap7Gax2LXdXfVjsVgslkjqHTzj/gZywl7eACiqUryBM/3j2RsAgSkSiTewQUXeAEQoQ0FzRTm7gf96AwDmm5DxqEjxDUBMMY3kjfnLO2Akw0q2/qf2Od7AVvAid7/pkdiW0pREmUIRkxBl9ac+mfpfl7z816vP/uuV3kVpNSzZSxqS9FL/2PpESfWM+xcuos7fjjDof2sntgaCAwUHCLSrxC/A/e1x9VrbogBaGpyzIkNBQ9iRtECgDCQvRIjw318eLkAqQdnW/U0iU6A4YEqkoqFEIsLk7c2BKoD3NwBnv6oEBUNVazy76Pnslf7sarsVuCUKofrW+erXtyNfvdZfvaPbBFY7QlOyoSlVezi/W41984P+5p8Pq68jn/uoP/fAeb4h4fPIZ/+uP/tUMIbpWJPf38DZ4+27fx7Rf+AOGQkX8IYvq89AokiglMfVyxxx2fFwqOEAIiryFH/4o7g18iDkLKbbQhD9uQvAy+3lBZzFRZqeARdwlpA0PhsxjyJq2dFqNNxAkf8S8Rc24is8WhZGKygNRQrFGW6PE2ljBksZSQu39rmwXvSLdZRf3O9ch169f//+F/3ZX4p8pDsJBhlmGxT+aH/jAkgV5uqJ8QJUgkCEIHvgMVi1/RNnDZry7QKz5IOVOmWSLAF8zpGH6gemyFK5Itte7VrA9qDvRrSb2UCRLRApeUiJwgheqEpAJVTWTEeBdnIvPRJRoQqSgtxLhZmeeV8SGnaBYIMpZ1sJR8n+4mwBR9FSq+FFmaQR2ojJC2V+OMoUv3h0nnsW0ZAolEBjM6JqA1EJhcQIYi70f1+IiCjrj1eVW+f93dj99UQ73a9hZSdZ61Ky2OgUJyPyuTTf1dXV5fX19eWHDx8ur97/cv3pKJ+esr3Z7rs2juIgFRcIJKL6c8RGVBpqeJchjASjaM8Cr2Bwu2cko2Gtv7TWFhkKM0Q3e7i9+7wetdbf/Xv//Xr39xINmsPvP+BuBfeV/9n1DvQP0IRcIiObdCC52nCeImGnAd6toE9mQ6XfBOFu1UoIzkio6A7f2f+xAcH9KidS6t8NcYmCMcq2gdwzj9luHRt0YJD7MBGc0b9Mume8vJB66tV/vFtBTqiomqJB7KcxOrs4Y1y96/yq/pGy7aSGBd47vBX8nKp2Vgs1pv2ZyjEfSXlI0oCymF/uUEjKu1AWWE8+J7tLm03rgD4d/TSe08i7lc0dSxcwmiDCHQ27Lm19ecyJu6hB5BrqyX63td0go2lKJYacRZUPh4UQeql+aKd+yGybqcDTjHe3cvYzfZoRRraYaZj7/hDdJskFYpZrSy8xNl4SVAkKY6OYCnwhaarHQemMdhasGdI9KPKMwHcogNjgYf0ACkaVNj9hxn1QFfkUQ/+bRt1mD6RExVxkgRadelyrObkGOe0bapNHk9+54bEK/7oj20GyMm3IszxFdcKQN3HebwXvaZ+bGFUntlVWe4g+ATQhVwHNBxO2U0d+I8c1xryqQS9q0gSJUBskCgiLmvFhHn9GQr8ZZzt+6VaMVcgOoXIu1BLJi1399a9rNKkSJI5pWHlthPab0buEXE1xXQ2/IeFzkft0jKcEwUptLCUMtE24rkYW14OMP6HzHffpPuAQ/brCIJ9WY7sdzuoxdWKXb4nCF7L30ue3GJMiVeBkVr3teFudPrguamFe+3TJriGvG545kWZx57s+2euu/y0jz/UUN9wUNI0C4TPj0GFnvfr67o9HkDxWL0RgucaolkictZPBCaSFSINjy6HZrCWbS42+f3uAmKYKzQO4iCiyIXLSWCF5/lMISZ6nupf1r07ho1z552uPnnv+VCNNX1iSnXewPrsxRXdUFLJCnICmEoFkcbtZLSdYbJezIEwpMv9of7at9uf6K1hNcE51EiwVSVOM3k6g3OZLQXYpf0/5hqRrwRWGquStws8Qao4oLGnIGQtsRcof4x87FMQ9IWtVurQ2DPXXJJyfFfkZZEiYBP3h5t80O8/RVh1IOmjyuh2eSzSfXUWjAdGu2WjNdRg/dwte1xy9VJdmZ4MiLNrszRrUrD8YV5AQFqU6xrpJbGrrfFd17viL+VbdnoRI2CCaOs/kuk5N6bOs86VZyKly+D7jj3MtW+ShcVXBaVU5y7n+RNhFSjbNilMfVpnKr2z5Zj1SvmmYdqHqzZdm0aY91qb0N+WCqv6FxazqcSnR7Uua54b+yx+dYdFe5DT6eRrbAguMVjGjabZpRP5LA7ov0ex2aK9nx1djvWRLrMl6+SaszJqAvteuTaYpS9c2y9JWmrRw7aQ8Cbm69J32rDWT7rQ6lXEpULVOHdoH1A+YC5oR0R/HZs1ajzmGNKb1noUOLZXQp/M4ZUOnP1ve1n+unjLVnGYj6YWzaV3htcaebuFr7y7Q8swGsHbSHl3H4X5G91+/svuvl+n+Y3YcUnjUS13E/okdXsXuwxDQWiY0lhinN+cnG79q04Q+SCl7DjLOqOKCsq3/TSetFFxrg1rblN0GHb6Y0LQQGISc2Q1JHleTpUhQCVGgBN1uUUggB9gOon7EyvbD1cxOA8zpCc8bNL+SrN6m0GHtntaYALesDwxCzvAGy/sv8QmntFyEezB7tShY0DsatfoFuH2H7cdWZepE9pJb8EK193V6O8Z0KPrYGabNNrdzhN/ufUrsfuzuNh83OZjf/eP3tf15uHs13c7uLA50u3zucTfVbrdr2cq2+13LfcsNQCobG62Pm/GwLV7t2LaZ3V1tfi43Vit+nM+2NBjYCn/q+q7CcQYc2AOvtQvMuMKAyIBIX2VIbR0rF1aF4oxnvJDwaLegn68e3wIrzAmFsfKBBvQdJ55cd0mUsmc596tUZJNSmWBUJnVmw6f7NJVQ5Kbu657/jXD7rvA+0cwesHPb9SRlIR5UdgsJL0SCRDXsdURKbbyg+yHPG+UIlJq07SSq6jl+6aRHEZer8HYjCWVQlfx5pAddDHu73ZfVgShNTcGfMqp01AHSWsPycXfOilTRIOF5oFR/dXWmUygODxr+/Onp4a2rampTG4XvEp43vV5eHg9HfZWX1+0DqEubevDkXKhJo98+gfOO82CeVx4QVRsStKnqjj0SPOMUQ8WFezb4k1yVWH+ESj30qG/FIpKZjDfGCI+Eo1mka9Q5rssdtCJoKQL8ESaEbdEySyikWczp/IyR1LTrnP7j9/Vb8zwWSaT9An80/4z6z4ONqw7EuRYGpN9RXtkPJqcfmM5KhM7jojLSDVu+O/Ao23re8XmLMWXu1IJyuz8FpgZFJjTXGewLIjPO1ZgGGx1wdgFn96z1Mxdw9p1JV3yK+he0ulFuEAUCldgHptd3xFvcKxP9HUnhvJ4V31aNagRnTUAHTh9pUp4jCyJMB3avzdhir2XBBmMuzLn3SPs9YfBHjgwylJJssUU9iEajFIOEp/3J4Uy7RSmClglKzx4d6xlm02cGumlHEuuZ0K1oh51ZYEx/BCnNaH9UnEedkR80K7JG/mgVleMzJAw2mjxEutMjUPCsfrB3/h7+ExgHQzVsbm0VbZSFUjZbHGiGdJNWvBBqcyMCz4g5Se3mA+MmF8Bwy5U9UNoasKONCOxzYk9t+Ya5QIlMyXrvfbpvPouuXcrUQdw6aBCzauriIYEot4TUZj+wsN2gols2w9aVNL/G1m2pQbvP+8csm8ltUOSRnhepz4VdPfS0Ib+vb1dPv9ZWrEbeZm88xCXObhyewMwLX3FDjUKbS0mqUGH3sjnwSSm93AaKK7NTzJehtTiNS9K0x7itsDaBy58x+8HKW13G03kiVdnDZLtUhK0XxVofWH3VlKtXxida0mCjENxzncvgaY80sivCE+lcpSFOSR6EvGCqP/893a7tM6+Nmg3N3O+ahZSESDjTEDlG5uiYEoRJUxBvRFJXPYn4iy29HMnIsC7F+G3X1wktkUUYopRxoee3Vkucn7crRcP76UxuKeIAmc6Ay6713pI/vv0G538UasMLFsE3sz78rdz7/Ra0dnp6CGH4QyU8DySmsb9F1T8bhyhdnD04QllIBKq03vLYpGYxdQydJLnFZB14xqaWsiUqoSLKiRjYSzarPU9a5jsjtEGJRJlnPscfVDXZDhqwwKHVsoawQZ3Zm4JHn32rrjl0ma6ly5bYK0bedNk9PDo5kHzsyUmR60F9GRGf16h8N0L1HHMgt6M34YXwqPhOi4OQZzlnZvdy7BQdY8goK7qB9VUUX6zAPg73iX4cicJGbu/hToseukmERAHZoSBbvLzKejXHKSddptGKIYnAidV+cAXWyuMMHxdj+Ah9Pd1viOUoro5jKCKf5aXJQ73moI10RGs4orvvSY0PHyxPgI3plylivgRAKXicQHGdlfkHsHJH9f/Fsw31le3X6q3YI9rDvLjUkcKX639ef4fCpOibvQlBkAseDt9qpPUfTF7+CNylXuMMrHs3gi+CSrV9Rk8g5zpP3iFolfYp1CAVjVKvVKakOTg3ao0vZKAaOVOjqdkd1ZhQn/oSIiJzCsyUuESRqzG/C+jA5DuToDqHNoVA4UDMn6tcCxy2d4YZF/sjU80MtXausZKPKY0FevPl3wTiBJU6d/el0lzfNq5yU8SxTulImHhr7Rcjun70anXYh7KHiqrFxgvJl+hpLRdkPnSPhFHrva+nKPXe21OUEnslsr8wvSoFjqlPaYhM4qVbRffqn3eFqluWOwWROye3inaEhRjBkz2+vBa4Qzb4vLbEG9usrfDHiRbqOSVRokKfMbpEEgUdGBTztlUaeY1s2yk6CkGlLAbcNTo81DtmEaKwaQdTwO3R0IXAHzkVA6tgDxRO/MCVqS2GZXdHWxwqoU9ZF4gUKglCrwdSV4VKuCjvBNSyQXF7yZk5XS3Kg/ZN3l7ImKZo0xbPu5p/qwTDgeAe5ZL+NT3ixVxkRN3AZn9Ycpk25dC/qn2kNUT5mTHWk+aFV7CuMl4wt0OquvKkhh3DPH0meQXrLZXPdm6BSu8h9ATLBjmKcGhfV38lrcTu/+boXirzJe0NDeMedHEPrOkdn5frN4aM7fmcd5cSFQZhlzLlKrCTxAnGOulxs+69agGk9Q3CLHKESsNEh5NzTPozBM1BUiL6V/7zYr+p0wsEwsCI7tzGcQxF5P0gs/vF3JHf0AyUwbf1l0GAjLLAO0RGmdkOdAqMNmFG0mU89jHlqnRZ85DiKMKy2eO4fs/+uTI+OaXZW4EogxBTSQe29s9YW9xasfDZip0A4twnUJj1nw2Zs5x1LqllorBrjQkkdl+bXxK3V24aSc5fUIwOinlLiEmDwgL8q4aE1e47YDeTdRuxqXTX/x6h2PF0YKvDnLqZOxbypxban6ZZreVg8Kq9HA1GKAgMuYiGXtBjKdxA8EvhRkKbwv6tlyVEoWhs+s6uZT2OBiuv44oTKQJZbP4XQxUkRCa+kVrCZ/I9434ZtlLwqVzRxvN+eidwBgf+yIOeusMrWMyCv7o8ES+qxceHq/cfrj9df/j46eOn/zn/QgRcf4LrDzcfP918/ATX7z9cwe9fnt6ehC9w5xm/IXSGOW2hK2DcK1AldQaRXo55hdECZ3D4rZ04gXN6yPPJzUrkEEvrG2+6dLu8OX1725zUFntsZ9LWXOyY24sdL91mw8uIZ2Rg3/C8Az9GXv9lkk7nCXRUBmY/9EJJUedo7aGq43SFROHV2787gaX5TjeYu20n8I4GaysZilczCtxSzoKYi2MHFmZBfjOizYO81vtZTqCz7w4NLKTHVYh9JakVO992Ic9yvxcefHYS7YUC5UHK08GGT6DOw7IXz1Jmk4pXGW2Xs4VeZPHn+qutSc+2W8KlGrp3Yd5dS1wquL+db61FLt9eNW7aLi+Tfp3hygtAPF0PW76p8PASzNeg7frf2TYfrvG6tvlzRLFJaejLcGsjzYvdKjBPZqvQfFhNmdciLxRHrPBXjghnvvqwrHdLNs7h+jGqu9Pckyu6OcOHK6Z8S1kweAz39Af4D1qgO5n6eqigUP0vkHoVGGXw/enzK/hojB5PLj84ca/JNP+vQKkCYzifWaYRa17OyfykKCXpFtUCSbHF3aLqeWuhN3QpU/MuBRsj/OM/Pj7YVyhYBa+Dd2/1WfD6uvbSt+/NRMfJ3IVKweFRk/kjqqzGs/ZBltKk9enC18LnAneUF9Ir/doJXQ7fHldewPJ2q004xfwt9snMixjcUueTzD6OTXOJYWAzHa8vXa8XO/driaFLpsYZlhv7p3FsX/xR/O7eVjYL5OmR+krFnuybSOAR3RVR9/bKMv3/1pfwZN7/3rjFQydt5+8vzX/KV7iwfSOV678v5QDf3sfisVdRvXDx7O55qc6mPj1SuF9fQMnKOLjbiEJg7itUQmRuP4r6bzvrYefK4+MEPRZ5yNPGJZX2mEzZgPOmpXP36al2HnpN24ywzkUVEruoh5hcDFyd00EUi3nyN5Q5ZxEaT56G8tO80o6uR5rRlJjbQwbGxBFSrz6oiUrPmhuThE9nM0CN2/9Og1lqhM6C8fteHxORZXWdf42j1Vy6e9n+pgqW/m0cLfL4BP6WxjHFd3eYphlh7obbWQZDny9d/pWFYm+39ZB0ywVVSTYPy++GhTsik9cS6XW8r/Fm9ty31/EW5hHDwrwBaeVivjbl+ePqbeMqnXHU540vUBfmdzwtMrR3tJnA+rgCgc+4p2z75v8DAAD//+EsS/8=" + return "eJzMne1v2ziTwL/3rxjkPjwpkLpNii7QAHeAn2Z3E6DtGk26z+G+CLQ0sniRSB1J2fX+9Qe+6NWSJTtU98liseu3mZ+GQ3JmRFJv4Bn3t5ATtnsFoKhK8RYu9MuLVwACUyQSb2GNirwCiFCGguaKcnYL//UKAMwvIeNRkeIrgJhiGslb88kbYCTDSrb+U/scb2EjeJG7d3oktqU0JVGmUMQkRFl91CdT/3XJy79effavV3oXpXVhyV7SkKQL/bL1jZLqGfc7LqLOZ0cY9N/Kia2B4EDBAQLtKvEL8HB3XL3WNiuAlgaXrMhQ0BC2JC0QKAPJCxEi/PeXz1cglaBs4z6TyBQoDpgSqWgokYgweX17oArg3S3Axa8qQcFQ1Rovrnq+e62/u9xsBG6IQqh+dbn89fXIT2/0T+/pJoHlltCUrGlK1R4u75djv3yvf/nn5+XXke990N/7zHm+JuHzyHd/0d99KhjDdOyS393CxePdm38d0X/gDhkJZ/CGL8tPQKJIoJTH1csccd7+cKjhACIq8hR/+KO4M/Ig5Cymm0IQ/b0rwMVmcQUXcZGmF8AFXCQkjS9GzKOImre3Gg23UORvI75jI77Co3lhtILSUKRQnOHmOJE2ZjCXkbRwa58r60VvraO8de+5Br1+9+7dW/3dt0U+0pwEgwyzNQp/tL9xAaQa5uqJ8QpUgkCEIHvgMVi1/RNnDZryzQyz5GcrdcokWQL4nCMP1Q9MkaVyRTa92rWAzUHbjWg3s4EiGyBS8pAShRHsqEpAJVTWTEeBtnIvPRJRoQqSgtxLhZmeeXcJDbtAsMaUs42Eo2R/cTaDo2ipVfeiTNII7YjJC2VeHGWKdx6d54FFNCQKJdDY9KjaQFRCITGCmAv9746IiLL+8apy67y/GbtvT7TTwwqWdpK1LiWLtQ5xMiKfS/NdX18vbm5uFu/fv19cv3t78/Eon56yvdnuuzaO4iAVF6ijAaq/SOyQSkNN70KEkdEo2rPAKxnc7RnJaFjrL821QYbC9NH1Hu7uP61GzfWLf/d/WG1/KdGg2f/+A+6X8FA5oE14oL+HJmSBjKzTgehqzXmKhJ0GeL+EPpkNlX4jhPtlKyK4IKGiW3xj/2NHBPdWTqTU7w1xiYIxyjaB3DOP4W49OOiRQe7DRHBG/zLxnvHyQuq5V394v4ScUFFdigax38bo4uqCcfWm81b9krLNpAsLvDd4a/RzqtphLdSY9jWVYz6S8pCkAWUxX2xRSMq7UBZYzz4nu0ubTeuAPh39NJ7jyPulDR5LFzCaIMItDbsubX15zIm7qEHkLnQhsd+rT7fhXW07kBhyFlUuHBZC6FT90Ez9jNkmU4GnGe9+6cxnmjQjjGww0zAP/SN0myQXiFmuDT1H19glqBIUxkYxFbgjaaq7QemLdhasGdI9KPKMwLcogNixw7oBFIwqbXnCjPegKvIphv43HXSbLZASFXORBVp06jFXc3INctrX0yZ3Jr9Tw2M1+uuGbI+RlWlDnuUpqhN6vBnm/Vbwnva5GaLqwLaKag/RJ4Am5Dqg+WC8dmrPb8S4xpjXNehVTZogEWqNRAFhUXN8OI8/I6HfgLM9fumrGKuQHULlXKg5Yheb/fXnNZpUCRLHNKy8NkL7y+hNQq6nuK6GX5Pwuch9OsZTgmClNjIJA23jreuR5HqQ8Sc0vuM+3Qccol9XGOTTamyzw0Xdp05s8g1RuCN7L21+hzEpUgVOZtXajrfV6INpUQvzxqdLdg150/DMiTSzO9/NyV5382858txMccN1QdMoED4jDj3srJZf3/zxCJLHakcElilGlSFx1g4GJ5AWIg2OZUNns5ZsLjT6/u0zxDRVaG7ARUSRNZGT+grJ859CSPI81a2s3zqFj3Lln6/dex74U400Pa8kW+9gfXZjim6pKGSFOAFNJQLJ7HazWk6w2DZnQZhSZP7R/mxb7c/VV7Ca4JLqIFgqkqYYvZ5AucnnguxS/p7yNUlXgisMVclbDT9DqDmisKQhZyywBSl/jH9sURB3h6xV6NLaMNQ/k3B5UeQXkCFhEvSXm59pdp6jLTiQdNDk9XV4rtB8chWNBkS7ZKM118P4pUt43eXoVF2aOokiLFrvTQ5q8g/GFSSERakeY90kNvXq5ijq3POd+VV9TQmRsEY0ZZ6D2k6j9jMO7bPK86VZ16lC+r62GOeat+ZD46qg06p5llP/ibCzVHCaBag+rDKyX9pqzmqkmtMw7UzFnC/NGk67601pb8oFVf15xlm15FKiW6Z0nhv6r4Z0ukU752m08zS2GfKNVm2jabZpRP4rBbot0Sx+aKe348lZL9kcKVov34RErQnoO5VtMk3JZNssc1tpUh7biYAScr3wHQWtNJNutDqycRFRlbYOLQvqB8wFzYjoH8fOmrUecwxpTOslDB1aKqFP53HKhk5/tryrP65uOtWcZl3plbNpXfC1xp5u4RvvLtDyzAawdtIeXcfhfkbz37yw+W/maf5jdhxSeNRL3Yj9Exu8GrsPh4BW1tDIOE6/nJ9s/OqaJrRBStlzkHFGFReUbfwvQWmF4Fob1NqmrD3o8MWEpoXAQCc71K9BP5UiQSVEgRJ0s0EhgRxgO4j6jivbDxc3OxdgNlN4Xq/5lWT1ooUOa3fzxgS4eX1gEPIMb7C8f4tPOKVlPu7B7FVSMKN3NEr3M3D7HrYfW4WqF7DTXGIYKLMnw+tS5Ye7ku5hJTEEq2KcYb4WPo1js/NH8bu7x3cWyNMj9VWUerL1O3jEFEPFBTwwqigx/7dawJNZNS0b604eVnD5bmH+KQufbN/In/orgQf4ucCYetyU8hXVjotnsHKrW6dPjxQeVldQsjIO0kaMITD3EyohwpgyjBZT2bniHnMsLS7kac8aensBl01L5+7bU+08dHPz9KLRigsFrDA7Lbqoh5hcqEmIYjZP/oYy5yxC48nTUH6aV9re9UgzmhIBisNAnzhC6tUHNVHpWeeOScKnsxkg7XBnwczVQ8+C8Vv+NiOyrLLeGkerWbgg+x+qYOk/xtGixGN5g8YxxTf3mKYZYS5KPctg6HOp4q8sFHtbdCHphguqkuw8rIRIj+a6JzJ5KVFKY/R4I+3JhIkxKtqNkB4xLMzNgqUb97U5Lx/NjuGjN9NauM9rX6BuqN/ytMg0c0aVGVwflyDwGfc6wHV/r7pIgheqvZPJ28b9Q9HHdu2vN7ktg/iNb3UrskaMW978dPUP894/f1/Z18NZgKbb2r10gb4un7s6zfoOt0/PyrZRRLlTrwFIZSPWOG7Gw2vxase2zex+QvO63ErYmXEO+OyVBgMZ1anhToXjDDiw61NrF5hxhQGRAZG+dqNo61i5sCwUZzzjhYRHu+nycvn4uowUx+6QaUDfqfCTay6JUvbcsfhVKrJOqUwwKuuWZoeT+zaVUORmpYNb8TbCPceahic9BDc2qUjKQjxYy1BI2BEJEtWw5xEptQGD7pc8bw8hUGrS9pOoqmC3dNSjiPMtZOiOJpRBtdCFR7rjxbC3gRSrB6M0NctcqE2GEUjrVg0fd+msSBUNEp4HSvUvIjjTKRSHzxr+8unp82t3816b2ih8k/C86flyAd8ZVXYxkmauO2XCc9mfFVUDlqfErH+xy3HVM6WtU/S7JXC+9jKbZYJ5ZYFqBbBupdqnRmg8msMS5Q2jDCD1r0qx80lsU2y3QNDfwP3YymvqKQ5TM8DKhOa6A5huChWGLNf6WJyLKzA7TutXGeqxvnxjeDgnmamLxxi5+1f+xqQVopBl+KUVQUsR4I8wIWyD9tq0n5hbPkyhYCQ1prik//x99dos4kQSaV/GH82PUX88eHHVKRruCgPSP+G+cMQ1lf+BiKBE6CwqKyeKYct3hwfKNp63id2ZAqB1O+W2jLW8bo1qh8iMPzYiiUYDaEd7YK3XXMDFd1Ym69Gw57leFwhUYh+YVt+S1HNqV4qFyzqweF1dWKPjawo6cGqBpuU5siDClOx9bs3V8mCNMRfm0KxI+z9h8EeODDKUkmywRT6IR6MUg4SnkW/7RSmClgsmQe5Y0XCb9jPgTXuSWAcV7h7YsGOb6l9gklmP1Bn5QbMia8yAVlHZV0PCYK3JQ6Rb3RsFz+qlgJfv4D+BcZtiD5tcW0UbZcYI2N5SbM4KJkrbEZf6E3hGzElqVzAbd7kChhuubJm61YFHLySwq0s9Xs83zAVKZKpxMyXdN1ex1q5l7qCW6eUkn6+u/aeMGUS5VF23xYHZbbSpL/WMBqik+W8BfT01bHf5sDP3cEAvN0GRR3oCpWwR8mIg7jmPq+6d2qTfV3fLp19re1adc703zuPSFNdVTyDnhfKKrkbRzfGH1ZhibyE6/ElplNwEiiuzJ8Wv0bVQDU3StMfQrVFwAp1vw/bjlWdJjucwRKqyzclmzmG5LkxonWB1VvP1jpxsU4OOQnDP9UaDpz3UyK4IT6RzFZ84JXlg2rs/iD7dru3DdhrpKs0a2VBZokqIhAsNkWNkDq1QgjBp1t40RlpXxYr4zpbAjoR0WJfE/F7X1wlXIoswRCnjQk+IrStxvt6u2A2f0GKCUxEHyHQYXTat9yv549tvcPlHoda8YBF8M8nob+Wu09egtdPTBxOGP1TC80BiGvvLzP7VOL7FjbsHh7cUEoEqrbc8sEWzmFqSjqxcRloPPmMTTnklKqEiyokY2LZy1vU8aZlvjNAGJRJllpcdXxPXZDu4gBmOyylLjmvUKYEps/TZt2qaQ5fpWrq8Enu44asuu4dbWAeSj93BKnIT9EfE5wGO341QPcccyO3oTXghPCq+1+Ig5FnOmdk3GTtFxxgyyoruwPoiii9W4HQOiSLwGXrU45wWPXR2IYkCskWhg4vrrFdznHLSZRqtTZIInFjtANdgzTvO8GE2hg/Q18T9hpiP4vo4hiLyWS5MKOo1AG3EIVrDEd19t8p8+GB56MSYfpki5nMAlILHCRTX4Zh/ACt3VP9fPFvT/pLoS9RbsUe0h3mx0COFL9f/tPoOhYnN13szBEEueDh8jqrWfzBr+SNw5wiPM7DucWy+CCrVdpEEgZzrAHmLoFXaW4CDVDRKvVKZIujgZKQ17shA/fJMjabCd1RjQn3qS4iIzMETpvYlilyN+V1ABybfMwmqoy+mECgcGPPPVa4FDts7w4yL/ZGp5gy1dq6xko8pjQV68+XfBOIElTpo96XSnBg9rnJdxLEO6UiYeLvaL0Z0fafX6pCmPHCoqMoydiSfo6W1XJD50NF1Rq33tp6i1HtrT1FK7FNY/A3Ty1LgmPqUhsgkLlz63Kv/vKc2uHzcKYjc/flltCUsxAie7IlJK4FbZIN3e0u8sQ2hCn+caKGendglKvQZo0skUdCBTnHesgcjrxFtO0VHIaiUxYC7RofnCI1ZhChs2sFUbns0dCHwR07FQPrrgcKJ12q5MqvKaGUcYLhFAX0EXUrzzeAYq6+dmqeS2e/Mu3vUMlEJfcq6QKRQSRB63bGwLFTCRXmCupYNitszoc1hVKI8l6zJ2wsZ0xRtyOV5T+BvlWA4ENyjXNK/po/WMRcZUbew3h/WiaZNl/SvahFyDTHGeNJc9gLGZcYLpmxoUZ0MORXy9LnvBaR3VD7b2RAqvacjFxKDHEU4tO6tv+hXYvf/cnTtmPmR9oEaBA4auAfWtI3PJ5A1Oopt95x3k58Kg7CFTLkK7LR2grFOul+uW69K2bS+QZhZDpbQMNFhOBGT/phGc5CUiP5axXkjvrmlIBAIAyO6c2ThMRSR94Oc3S7mQWINzUAZfFt9GQTIKAu8Q2SUmSVPp8BoE2YkncdjH1NerbY191OOIswb747r9+yfS+OTUy57IxBlEGIq6cBukDOyoTsrFj5ZsRNAnPsECrP+ReDnJODOJbVMFDY7mkBi1+75JXHrAaeR5HyH4u/sFBbg7+oSVrvvAbsZotsRm0r3jJQjFFueDqzKOKfS53YR/XkgtK207AtelZedwQgFgSEX0dBDTC2F6wd+KVxHmEARolA0No1m026Pa5OsvI4PTqQIZLH+XwxV4Hdrco/wM/mecT8PWyn4VK5o7XnjgBN4Bgf+yIOeEskLWEx+Xx0tj1dV1vH++t37m4837z98/PDxfy6/EAE3H+Hm/e2Hj7cfPsLNu/fX8PuXp9cn4QvcesZvCD3DnLYmFzCPxz40pZ5BpPMwrzBa4BkcfkslTuA5LeR5l28l8hjLqy7UNm9O197WTbXFHls0tTGn3ef2tPuFWwe5iHhGqM/DRo28/hP2nc4T6KgMzNLtmYKgzu7rQ1XH6QqJwquTf3cCS/OdbjB35mjgHQ1WVjIUL2YUuKGcBTEXbq+FP8hvRrS51dh6ZuUJdJIXIsTAQvojezRiwYo933Yhz3K/Z2J8chLtmRPlRtHTwTzvyP1kn8ZBmY0lXmS0bc5merrfn6uvtgJ9tt0SLtXQ0Rznne/DpWqceHg60SxPJFo2Hj9UPmHnZYYrz4jxtGG+fHz74aEBL0Hb9j/H+ny4xiOsz58jinVKQ1+GWxlpXuxWgXkyW4Xmw2r2LKmZxhEr/IU9wpmv3gDs3ZKNvcV+jOoe9OTJFd2c4cMVU76hLDhYjXb+EoPPWiA0Tzh7CVRQqP6NdS8Cowy+P316AZ87w62X7IwTQzpHwp0Taf5fgVIFxnA+o0wjFoxYPyFKSbpBNUNQbHE3qHqe5O4NXcrUPGDOjhH+8R8fP9vnylkFL4N3jzqd8Yjndurb97jW42TuvK3gcDPM+T2qrL6z9lab0qT1xseXwucCt5QX0iv9ygmdD9/uqZ7B8nZBTTjF/C9jn8Xwlj6fZP5+/P8PAAD//98j+x4=" } diff --git a/x-pack/metricbeat/modules.d/panw.yml.disabled b/x-pack/metricbeat/modules.d/panw.yml.disabled index 74ffb4fc5fe..72242e7c7aa 100644 --- a/x-pack/metricbeat/modules.d/panw.yml.disabled +++ b/x-pack/metricbeat/modules.d/panw.yml.disabled @@ -2,17 +2,8 @@ # Docs: https://www.elastic.co/guide/en/beats/metricbeat/main/metricbeat-module-panw.html - module: panw - metricsets: - - "interfaces" - - "system" - - "routing" - - "vpn" - + metricsets: ["licenses"] enabled: false period: 10s - host_ip: "127.0.0.1" - port: - api_key: "" - api_debug_mode: false - + hosts: ["localhost"] From 181a0bbab609d1e0256faccef2f7cd87f37ddae8 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Tue, 17 Sep 2024 15:45:53 +0530 Subject: [PATCH 26/32] remove mappings & make update --- NOTICE.txt | 25 ++ metricbeat/docs/fields.asciidoc | 13 + metricbeat/docs/modules_list.asciidoc | 6 + .../metricbeat/module/panw/_meta/fields.yml | 7 +- x-pack/metricbeat/module/panw/fields.go | 2 +- .../module/panw/interfaces/_meta/fields.yml | 407 +----------------- .../module/panw/routing/_meta/fields.yml | 159 +------ .../module/panw/system/_meta/fields.yml | 298 +------------ .../module/panw/vpn/_meta/fields.yml | 123 +----- 9 files changed, 52 insertions(+), 988 deletions(-) diff --git a/NOTICE.txt b/NOTICE.txt index e691397655f..d807ab2e651 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -2720,6 +2720,31 @@ Redistribution and use in source and binary forms, with or without modification, THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +Dependency : github.com/PaloAltoNetworks/pango +Version: v0.10.2 +Licence type (autodetected): ISC +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/!palo!alto!networks/pango@v0.10.2/LICENSE: + +Distributed under ISC license: + +Copyright (c) 2014-2016, Palo Alto Networks Inc. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + -------------------------------------------------------------------------------- Dependency : github.com/elastic/sarama Version: v1.19.1-0.20220310193331-ebc2b0d8eef3 diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 6a626d44cae..1b42abbab9a 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -68,6 +68,7 @@ grouped in the following categories: * <> * <> * <> +* <> * <> * <> * <> @@ -57140,6 +57141,18 @@ format: bytes -- +[[exported-fields-panw]] +== Panw fields + +PAN-OS module + + +[float] +=== panw + +PAN-OS module + + [[exported-fields-php_fpm]] == PHP_FPM fields diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index 1942747c02c..51bf048ab03 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -244,6 +244,11 @@ This file is generated! See scripts/mage/docs_collector.go .3+| .3+| |<> |<> beta[] |<> +|<> beta[] |image:./images/icon-no.png[No prebuilt dashboards] | +.4+| .4+| |<> beta[] +|<> beta[] +|<> beta[] +|<> beta[] |<> |image:./images/icon-no.png[No prebuilt dashboards] | .2+| .2+| |<> |<> @@ -373,6 +378,7 @@ include::modules/nats.asciidoc[] include::modules/nginx.asciidoc[] include::modules/openmetrics.asciidoc[] include::modules/oracle.asciidoc[] +include::modules/panw.asciidoc[] include::modules/php_fpm.asciidoc[] include::modules/postgresql.asciidoc[] include::modules/prometheus.asciidoc[] diff --git a/x-pack/metricbeat/module/panw/_meta/fields.yml b/x-pack/metricbeat/module/panw/_meta/fields.yml index 2296a368bab..18f74261819 100644 --- a/x-pack/metricbeat/module/panw/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/_meta/fields.yml @@ -1,10 +1,9 @@ - key: panw - title: "panw" + title: "Panw" + description: PAN-OS module release: beta - description: > - panw module fields: - name: panw type: group - description: > + description: PAN-OS module fields: diff --git a/x-pack/metricbeat/module/panw/fields.go b/x-pack/metricbeat/module/panw/fields.go index b3fc09aa118..d5044241669 100644 --- a/x-pack/metricbeat/module/panw/fields.go +++ b/x-pack/metricbeat/module/panw/fields.go @@ -19,5 +19,5 @@ func init() { // AssetPanw returns asset data. // This is the base64 encoded zlib format compressed contents of module/panw. func AssetPanw() string { - return "eJzMne1v2ziTwL/3rxjkPjwpkLpNii7QAHeAn2Z3E6DtGk26z+G+CLQ0sniRSB1J2fX+9Qe+6NWSJTtU98liseu3mZ+GQ3JmRFJv4Bn3t5ATtnsFoKhK8RYu9MuLVwACUyQSb2GNirwCiFCGguaKcnYL//UKAMwvIeNRkeIrgJhiGslb88kbYCTDSrb+U/scb2EjeJG7d3oktqU0JVGmUMQkRFl91CdT/3XJy79effavV3oXpXVhyV7SkKQL/bL1jZLqGfc7LqLOZ0cY9N/Kia2B4EDBAQLtKvEL8HB3XL3WNiuAlgaXrMhQ0BC2JC0QKAPJCxEi/PeXz1cglaBs4z6TyBQoDpgSqWgokYgweX17oArg3S3Axa8qQcFQ1Rovrnq+e62/u9xsBG6IQqh+dbn89fXIT2/0T+/pJoHlltCUrGlK1R4u75djv3yvf/nn5+XXke990N/7zHm+JuHzyHd/0d99KhjDdOyS393CxePdm38d0X/gDhkJZ/CGL8tPQKJIoJTH1csccd7+cKjhACIq8hR/+KO4M/Ig5Cymm0IQ/b0rwMVmcQUXcZGmF8AFXCQkjS9GzKOImre3Gg23UORvI75jI77Co3lhtILSUKRQnOHmOJE2ZjCXkbRwa58r60VvraO8de+5Br1+9+7dW/3dt0U+0pwEgwyzNQp/tL9xAaQa5uqJ8QpUgkCEIHvgMVi1/RNnDZryzQyz5GcrdcokWQL4nCMP1Q9MkaVyRTa92rWAzUHbjWg3s4EiGyBS8pAShRHsqEpAJVTWTEeBtnIvPRJRoQqSgtxLhZmeeXcJDbtAsMaUs42Eo2R/cTaDo2ipVfeiTNII7YjJC2VeHGWKdx6d54FFNCQKJdDY9KjaQFRCITGCmAv9746IiLL+8apy67y/GbtvT7TTwwqWdpK1LiWLtQ5xMiKfS/NdX18vbm5uFu/fv19cv3t78/Eon56yvdnuuzaO4iAVF6ijAaq/SOyQSkNN70KEkdEo2rPAKxnc7RnJaFjrL821QYbC9NH1Hu7uP61GzfWLf/d/WG1/KdGg2f/+A+6X8FA5oE14oL+HJmSBjKzTgehqzXmKhJ0GeL+EPpkNlX4jhPtlKyK4IKGiW3xj/2NHBPdWTqTU7w1xiYIxyjaB3DOP4W49OOiRQe7DRHBG/zLxnvHyQuq5V394v4ScUFFdigax38bo4uqCcfWm81b9krLNpAsLvDd4a/RzqtphLdSY9jWVYz6S8pCkAWUxX2xRSMq7UBZYzz4nu0ubTeuAPh39NJ7jyPulDR5LFzCaIMItDbsubX15zIm7qEHkLnQhsd+rT7fhXW07kBhyFlUuHBZC6FT90Ez9jNkmU4GnGe9+6cxnmjQjjGww0zAP/SN0myQXiFmuDT1H19glqBIUxkYxFbgjaaq7QemLdhasGdI9KPKMwLcogNixw7oBFIwqbXnCjPegKvIphv43HXSbLZASFXORBVp06jFXc3INctrX0yZ3Jr9Tw2M1+uuGbI+RlWlDnuUpqhN6vBnm/Vbwnva5GaLqwLaKag/RJ4Am5Dqg+WC8dmrPb8S4xpjXNehVTZogEWqNRAFhUXN8OI8/I6HfgLM9fumrGKuQHULlXKg5Yheb/fXnNZpUCRLHNKy8NkL7y+hNQq6nuK6GX5Pwuch9OsZTgmClNjIJA23jreuR5HqQ8Sc0vuM+3Qccol9XGOTTamyzw0Xdp05s8g1RuCN7L21+hzEpUgVOZtXajrfV6INpUQvzxqdLdg150/DMiTSzO9/NyV5382858txMccN1QdMoED4jDj3srJZf3/zxCJLHakcElilGlSFx1g4GJ5AWIg2OZUNns5ZsLjT6/u0zxDRVaG7ARUSRNZGT+grJ859CSPI81a2s3zqFj3Lln6/dex74U400Pa8kW+9gfXZjim6pKGSFOAFNJQLJ7HazWk6w2DZnQZhSZP7R/mxb7c/VV7Ca4JLqIFgqkqYYvZ5AucnnguxS/p7yNUlXgisMVclbDT9DqDmisKQhZyywBSl/jH9sURB3h6xV6NLaMNQ/k3B5UeQXkCFhEvSXm59pdp6jLTiQdNDk9XV4rtB8chWNBkS7ZKM118P4pUt43eXoVF2aOokiLFrvTQ5q8g/GFSSERakeY90kNvXq5ijq3POd+VV9TQmRsEY0ZZ6D2k6j9jMO7bPK86VZ16lC+r62GOeat+ZD46qg06p5llP/ibCzVHCaBag+rDKyX9pqzmqkmtMw7UzFnC/NGk67601pb8oFVf15xlm15FKiW6Z0nhv6r4Z0ukU752m08zS2GfKNVm2jabZpRP4rBbot0Sx+aKe348lZL9kcKVov34RErQnoO5VtMk3JZNssc1tpUh7biYAScr3wHQWtNJNutDqycRFRlbYOLQvqB8wFzYjoH8fOmrUecwxpTOslDB1aKqFP53HKhk5/tryrP65uOtWcZl3plbNpXfC1xp5u4RvvLtDyzAawdtIeXcfhfkbz37yw+W/maf5jdhxSeNRL3Yj9Exu8GrsPh4BW1tDIOE6/nJ9s/OqaJrRBStlzkHFGFReUbfwvQWmF4Fob1NqmrD3o8MWEpoXAQCc71K9BP5UiQSVEgRJ0s0EhgRxgO4j6jivbDxc3OxdgNlN4Xq/5lWT1ooUOa3fzxgS4eX1gEPIMb7C8f4tPOKVlPu7B7FVSMKN3NEr3M3D7HrYfW4WqF7DTXGIYKLMnw+tS5Ye7ku5hJTEEq2KcYb4WPo1js/NH8bu7x3cWyNMj9VWUerL1O3jEFEPFBTwwqigx/7dawJNZNS0b604eVnD5bmH+KQufbN/In/orgQf4ucCYetyU8hXVjotnsHKrW6dPjxQeVldQsjIO0kaMITD3EyohwpgyjBZT2bniHnMsLS7kac8aensBl01L5+7bU+08dHPz9KLRigsFrDA7Lbqoh5hcqEmIYjZP/oYy5yxC48nTUH6aV9re9UgzmhIBisNAnzhC6tUHNVHpWeeOScKnsxkg7XBnwczVQ8+C8Vv+NiOyrLLeGkerWbgg+x+qYOk/xtGixGN5g8YxxTf3mKYZYS5KPctg6HOp4q8sFHtbdCHphguqkuw8rIRIj+a6JzJ5KVFKY/R4I+3JhIkxKtqNkB4xLMzNgqUb97U5Lx/NjuGjN9NauM9rX6BuqN/ytMg0c0aVGVwflyDwGfc6wHV/r7pIgheqvZPJ28b9Q9HHdu2vN7ktg/iNb3UrskaMW978dPUP894/f1/Z18NZgKbb2r10gb4un7s6zfoOt0/PyrZRRLlTrwFIZSPWOG7Gw2vxase2zex+QvO63ErYmXEO+OyVBgMZ1anhToXjDDiw61NrF5hxhQGRAZG+dqNo61i5sCwUZzzjhYRHu+nycvn4uowUx+6QaUDfqfCTay6JUvbcsfhVKrJOqUwwKuuWZoeT+zaVUORmpYNb8TbCPceahic9BDc2qUjKQjxYy1BI2BEJEtWw5xEptQGD7pc8bw8hUGrS9pOoqmC3dNSjiPMtZOiOJpRBtdCFR7rjxbC3gRSrB6M0NctcqE2GEUjrVg0fd+msSBUNEp4HSvUvIjjTKRSHzxr+8unp82t3816b2ih8k/C86flyAd8ZVXYxkmauO2XCc9mfFVUDlqfErH+xy3HVM6WtU/S7JXC+9jKbZYJ5ZYFqBbBupdqnRmg8msMS5Q2jDCD1r0qx80lsU2y3QNDfwP3YymvqKQ5TM8DKhOa6A5huChWGLNf6WJyLKzA7TutXGeqxvnxjeDgnmamLxxi5+1f+xqQVopBl+KUVQUsR4I8wIWyD9tq0n5hbPkyhYCQ1prik//x99dos4kQSaV/GH82PUX88eHHVKRruCgPSP+G+cMQ1lf+BiKBE6CwqKyeKYct3hwfKNp63id2ZAqB1O+W2jLW8bo1qh8iMPzYiiUYDaEd7YK3XXMDFd1Ym69Gw57leFwhUYh+YVt+S1HNqV4qFyzqweF1dWKPjawo6cGqBpuU5siDClOx9bs3V8mCNMRfm0KxI+z9h8EeODDKUkmywRT6IR6MUg4SnkW/7RSmClgsmQe5Y0XCb9jPgTXuSWAcV7h7YsGOb6l9gklmP1Bn5QbMia8yAVlHZV0PCYK3JQ6Rb3RsFz+qlgJfv4D+BcZtiD5tcW0UbZcYI2N5SbM4KJkrbEZf6E3hGzElqVzAbd7kChhuubJm61YFHLySwq0s9Xs83zAVKZKpxMyXdN1ex1q5l7qCW6eUkn6+u/aeMGUS5VF23xYHZbbSpL/WMBqik+W8BfT01bHf5sDP3cEAvN0GRR3oCpWwR8mIg7jmPq+6d2qTfV3fLp19re1adc703zuPSFNdVTyDnhfKKrkbRzfGH1ZhibyE6/ElplNwEiiuzJ8Wv0bVQDU3StMfQrVFwAp1vw/bjlWdJjucwRKqyzclmzmG5LkxonWB1VvP1jpxsU4OOQnDP9UaDpz3UyK4IT6RzFZ84JXlg2rs/iD7dru3DdhrpKs0a2VBZokqIhAsNkWNkDq1QgjBp1t40RlpXxYr4zpbAjoR0WJfE/F7X1wlXIoswRCnjQk+IrStxvt6u2A2f0GKCUxEHyHQYXTat9yv549tvcPlHoda8YBF8M8nob+Wu09egtdPTBxOGP1TC80BiGvvLzP7VOL7FjbsHh7cUEoEqrbc8sEWzmFqSjqxcRloPPmMTTnklKqEiyokY2LZy1vU8aZlvjNAGJRJllpcdXxPXZDu4gBmOyylLjmvUKYEps/TZt2qaQ5fpWrq8Enu44asuu4dbWAeSj93BKnIT9EfE5wGO341QPcccyO3oTXghPCq+1+Ig5FnOmdk3GTtFxxgyyoruwPoiii9W4HQOiSLwGXrU45wWPXR2IYkCskWhg4vrrFdznHLSZRqtTZIInFjtANdgzTvO8GE2hg/Q18T9hpiP4vo4hiLyWS5MKOo1AG3EIVrDEd19t8p8+GB56MSYfpki5nMAlILHCRTX4Zh/ACt3VP9fPFvT/pLoS9RbsUe0h3mx0COFL9f/tPoOhYnN13szBEEueDh8jqrWfzBr+SNw5wiPM7DucWy+CCrVdpEEgZzrAHmLoFXaW4CDVDRKvVKZIujgZKQ17shA/fJMjabCd1RjQn3qS4iIzMETpvYlilyN+V1ABybfMwmqoy+mECgcGPPPVa4FDts7w4yL/ZGp5gy1dq6xko8pjQV68+XfBOIElTpo96XSnBg9rnJdxLEO6UiYeLvaL0Z0fafX6pCmPHCoqMoydiSfo6W1XJD50NF1Rq33tp6i1HtrT1FK7FNY/A3Ty1LgmPqUhsgkLlz63Kv/vKc2uHzcKYjc/flltCUsxAie7IlJK4FbZIN3e0u8sQ2hCn+caKGendglKvQZo0skUdCBTnHesgcjrxFtO0VHIaiUxYC7RofnCI1ZhChs2sFUbns0dCHwR07FQPrrgcKJ12q5MqvKaGUcYLhFAX0EXUrzzeAYq6+dmqeS2e/Mu3vUMlEJfcq6QKRQSRB63bGwLFTCRXmCupYNitszoc1hVKI8l6zJ2wsZ0xRtyOV5T+BvlWA4ENyjXNK/po/WMRcZUbew3h/WiaZNl/SvahFyDTHGeNJc9gLGZcYLpmxoUZ0MORXy9LnvBaR3VD7b2RAqvacjFxKDHEU4tO6tv+hXYvf/cnTtmPmR9oEaBA4auAfWtI3PJ5A1Oopt95x3k58Kg7CFTLkK7LR2grFOul+uW69K2bS+QZhZDpbQMNFhOBGT/phGc5CUiP5axXkjvrmlIBAIAyO6c2ThMRSR94Oc3S7mQWINzUAZfFt9GQTIKAu8Q2SUmSVPp8BoE2YkncdjH1NerbY191OOIswb747r9+yfS+OTUy57IxBlEGIq6cBukDOyoTsrFj5ZsRNAnPsECrP+ReDnJODOJbVMFDY7mkBi1+75JXHrAaeR5HyH4u/sFBbg7+oSVrvvAbsZotsRm0r3jJQjFFueDqzKOKfS53YR/XkgtK207AtelZedwQgFgSEX0dBDTC2F6wd+KVxHmEARolA0No1m026Pa5OsvI4PTqQIZLH+XwxV4Hdrco/wM/mecT8PWyn4VK5o7XnjgBN4Bgf+yIOeEskLWEx+Xx0tj1dV1vH++t37m4837z98/PDxfy6/EAE3H+Hm/e2Hj7cfPsLNu/fX8PuXp9cn4QvcesZvCD3DnLYmFzCPxz40pZ5BpPMwrzBa4BkcfkslTuA5LeR5l28l8hjLqy7UNm9O197WTbXFHls0tTGn3ef2tPuFWwe5iHhGqM/DRo28/hP2nc4T6KgMzNLtmYKgzu7rQ1XH6QqJwquTf3cCS/OdbjB35mjgHQ1WVjIUL2YUuKGcBTEXbq+FP8hvRrS51dh6ZuUJdJIXIsTAQvojezRiwYo933Yhz3K/Z2J8chLtmRPlRtHTwTzvyP1kn8ZBmY0lXmS0bc5merrfn6uvtgJ9tt0SLtXQ0Rznne/DpWqceHg60SxPJFo2Hj9UPmHnZYYrz4jxtGG+fHz74aEBL0Hb9j/H+ny4xiOsz58jinVKQ1+GWxlpXuxWgXkyW4Xmw2r2LKmZxhEr/IU9wpmv3gDs3ZKNvcV+jOoe9OTJFd2c4cMVU76hLDhYjXb+EoPPWiA0Tzh7CVRQqP6NdS8Cowy+P316AZ87w62X7IwTQzpHwp0Taf5fgVIFxnA+o0wjFoxYPyFKSbpBNUNQbHE3qHqe5O4NXcrUPGDOjhH+8R8fP9vnylkFL4N3jzqd8Yjndurb97jW42TuvK3gcDPM+T2qrL6z9lab0qT1xseXwucCt5QX0iv9ygmdD9/uqZ7B8nZBTTjF/C9jn8Xwlj6fZP5+/P8PAAD//98j+x4=" + return "eJyszUEKwjAUhOF9TjF0nwu8nRfQgid4mlGCaRKSV0pvL0URceGqs/wX33g8uAqq5sUBFi1RMIyal8EBgf3aYrVYsmA8HP3pjKmEOdEBjYnaKbjQ1AG3yBS6OADwyDrx426ztVJwb2Wu7/JX3/YtvtTfz336MwAA//80X0nz" } diff --git a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml index f46c4751817..05c31ead2f9 100644 --- a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml @@ -1,406 +1 @@ -- name: interfaces - type: group - release: beta - description: > - interfaces - fields: - - name: physical.name - type: keyword - description: > - Physical interface name - - name: physical.id - type: keyword - description: > - Physical interface ID - - name: physical.type - type: keyword - description: > - Physical interface type (numeric value in source XML, string value sent to elasticsearch): - 0: "Ethernet interface", - 1: "Aggregate Ethernet (AE) interface", - 2: "High Availability (HA) interface", - 3: "VLAN interface", - 5: "Loopback interface", - 6: "Tunnel interface", - 10: "SD-WAN interface", - - name: physical.mac - type: keyword - description: > - Physical MAC address - - name: physical.speed - type: keyword - description: > - Physical interface speed - - name: physical.duplex - type: keyword - description: > - Duplex configuration, e.g., "full" or "half" - - name: physical.state - type: keyword - description: > - Physical interface state: up/down - - name: physical.mode - type: keyword - description: > - Physical interface mode, e.g., autoneg - - name: physical.full_state - type: keyword - description: > - Physical full state, speed/duplex/state, e.g., "1000/full/up" - - name: physical.ae_member - type: keyword - description: > - For aggregate interfaces, the array of member interfaces - - name: logical.name - type: keyword - description: > - Logical interface name - - name: logical.id - type: keyword - description: > - Logical interface ID - - name: logical.tag - type: integer - description: > - VLAN tag associated with this interface - - name: logical.vsys - type: integer - description: > - Virtual system to which this interface belongs - - name: logical.zone - type: keyword - description: > - Logical zone, e.g., "inside" or "outside" - - name: logical.fwd - type: keyword - description: > - Indicates if the interface is used for forwarding - - name: logical.ip - type: ip - description: > - Logical IP Address with subnet mask, e.g., 111.222.333.10/29 - - name: logical.addr - type: keyword - description: > - Used to store additional static IP addresses - - name: logical.dyn_addr - type: keyword - description: > - Dynamic addresses, e.g., generated by DHCP - - name: logical.addr6 - type: keyword - description: > - Logical IPv6 address - # HA Interface fields - - name: ha.enabled - type: boolean - description: > - HA enabled - - name: ha.mode - type: keyword - description: > - HA mode, e.g., "active-active" or "active-passive" - - name: ha.running_sync - type: keyword - description: > - Indicates the sychronization status of the HA pair, e.g., "synchronized","not-synchronized","synchronizing" - - name: ha.running_sync_enabled - type: boolean - description: > - Indicates if running configuration synchronization is enabled - - name: ha.local_info.version - type: long - description: > - HA configuration info version - - name: ha.local_info.state - type: keyword - description: > - HA state of the local device, e.g., "active" or "passive" - - name: ha.local_info.state_duration.sec - type: long - description: > - Duration in seconds of the current state - - name: ha.local_info.mgmt_ip - type: ip - description: > - HA local info management IP - - name: ha.local_info.preemptive - type: boolean - description: > - Indicates whether the firewall is configured to preemptively take over as the active unit in an HA setup - - name: ha.local_info.mode - type: keyword - description: > - HA mode, e.g., "active-active" or "active-passive" - - name: ha.local_info.platform_model - type: keyword - description: > - Platform model of the local device - - name: ha.local_info.state_sync - type: keyword - description: > - Status of HA synchronization, e.g., "complete" - - name: ha.local_info.state_sync_type - type: keyword - description: > - Type of interface used for HA synchronization - - name: ha.local_info.ha1_ipaddr - type: ip - description: > - IP Address of HA1 interface, used for heartbeat and management synchronization - - name: ha.local_info.ha1_macaddr - type: keyword - description: > - HA local info HA1 MAC address - - name: ha.local_info.ha1_port - type: keyword - description: > - Indicates which interface is used for HA1 traffic, e.g., "dedicated-ha1" - - name: ha.local_info.ha1_backup_ipaddr - type: ip - description: > - The backup IP address for the HA1 interface - - name: ha.local_info.ha1_backup_macaddr - type: keyword - description: > - HA local info HA1 backup MAC address - - name: ha.local_info.ha1_backup_port - type: keyword - description: > - HA local info HA1 backup port, e.g. "management" - - name: ha.local_info.ha1_backup_gateway - type: ip - description: > - Default gateway for the backup HA1 interface - - name: ha.local_info.ha2_ipaddr - type: ip - description: > - HA local info HA2 IP address - - name: ha.local_info.ha2_macaddr - type: keyword - description: > - HA local info HA2 MAC address - - name: ha.local_info.ha2_port - type: keyword - description: > - Indicates which interface is used for HA1 traffic, e.g., "dedicated-ha2" - - name: ha.local_info.build_rel - type: keyword - description: > - The PAN-OS software version running on the firewall - - name: ha.local_info.url_version - type: keyword - description: > - The version of the URL filtering database - - name: ha.local_info.app_version - type: keyword - description: > - The version of the application database - - name: ha.local_info.iot_version - type: keyword - description: > - HA local info IoT database version - - name: ha.local_info.av_version - type: keyword - description: > - The version of the antivirus database - - name: ha.local_info.threat_version - type: keyword - description: > - HA local info threat version - - name: ha.local_info.vpn_client_version - type: keyword - description: > - Version of the VPN client (if installed) - - name: ha.local_info.gp_client_version - type: keyword - description: > - Version of the GlobalProtect client software - - name: ha.peer_info.conn_status - type: keyword - description: > - Overall status of the HA connections ("up" means all connections are operational) - - name: ha.peer_info.state - type: keyword - description: > - Current operational state of the peer firewall (passive means it is in standby mode and not handling traffic) - - name: ha.peer_info.state_duration.sec - type: long - description: > - How long the peer has been in the current state in seconds - - name: ha.peer_info.mgmt_ip - type: ip - description: > - Management IP address of the peer firewall - - name: ha.peer_info.preemptive - type: boolean - description: > - Indicates if preemption is enabled on the peer firewall - - name: ha.peer_info.mode - type: keyword - description: > - HA mode configured on the peer firewall, e.g. "Active-Passive" - - name: ha.peer_info.platform_model - type: keyword - description: > - Model of the peer firewall - - name: ha.peer_info.priority - type: long - description: > - HA priority value of the peer firewall - - name: ha.peer_info.ha1_ipaddr - type: ip - description: > - IP address of the HA1 interface on the peer - - name: ha.peer_info.ha1_macaddr - type: keyword - description: > - HA1 MAC address of the peer - - name: ha.peer_info.ha1_backup_ipaddr - type: ip - description: > - HA peer info HA1 backup IP address - - name: ha.peer_info.ha1_backup_macaddr - type: keyword - description: > - HA peer info HA1 backup MAC address - - name: ha.peer_info.ha2_ipaddr - type: ip - description: > - HA peer info HA2 IP address - - name: ha.peer_info.ha2_macaddr - type: keyword - description: > - HA peer info HA2 MAC address - - name: ha.peer_info.conn_ha1.status - type: keyword - description: > - Peer HA1 connection status, e.g., "up" - - name: ha.peer_info.conn_ha1.primary - type: boolean - description: > - Specifies if the HA1 connection is primary - - name: ha.peer_info.conn_ha1.description - type: keyword - description: > - Description of the connection type ,e.g., "heartbeat status" - - name: ha.peer_info.conn_ha2.status - type: keyword - description: > - HA peer info connection HA2 status - - name: ha.peer_info.conn_ha2.primary - type: boolean - description: > - Specifies if the HA2 connection is primary - - name: ha.peer_info.conn_ha2.description - type: keyword - description: > - HA peer info connection HA2 description - - name: ha.peer_info.conn_ha1_backup.status - type: keyword - description: > - HA peer info connection HA1 backup status, e.g., "up" means it is operational - - name: ha.peer_info.conn_ha1_backup.description - type: keyword - description: > - HA peer info connection HA1 backup description - - name: ha.link_monitoring.enabled - type: boolean - description: > - Indicates if link monitoring is enabled - - name: ha.link_monitoring.failure_condition - type: keyword - description: > - Condition that triggers a link monitoring failure, e.g., "any" - - name: ha.link_monitoring.group.name - type: keyword - description: > - Name of the link monitoring group - - name: ha.link_monitoring.group.enabled - type: boolean - description: > - Indicates if the link monitoring group is enabled - - name: ha.link_monitoring.group.failure_condition - type: keyword - description: > - Condition that triggers a failure in the link monitoring group - - name: ha.link_monitoring.group.interface.name - type: keyword - description: > - Name of the interface in the link monitoring group - - name: ha.link_monitoring.group.interface.status - type: keyword - description: > - Status of the interface in the link monitoring group - - name: ipsec_tunnel.id - type: keyword - description: > - ID of the IPsec tunnel - - name: ipsec_tunnel.name - type: keyword - description: > - Name of the IPsec tunnel - - name: ipsec_tunnel.gw - type: keyword - description: > - Gateway of the IPsec tunnel - - name: ipsec_tunnel.TSi_ip - type: ip - description: > - Traffic Selector Initiator IP. This is the local IP (0.0.0.0 means any IP address) - - name: ipsec_tunnel.TSi_prefix - type: keyword - description: > - Network prefix for the TSi IP, 0 means no specific network is defined. - - name: ipsec_tunnel.TSi_proto - type: keyword - description: > - Protocol associated with the TSi (0 means any protocol) - - name: ipsec_tunnel.TSi_port - type: long - description: > - Port number associated with TSi (0 means any port) - - name: ipsec_tunnel.TSr_ip - type: ip - description: > - Traffic Selector Responder IP. - - name: ipsec_tunnel.TSr_prefix - type: keyword - description: > - Network prefix for the TSr IP. Similar to TSi_prefix - - name: ipsec_tunnel.TSr_proto - type: keyword - description: > - TSr protocol of the IPsec tunnel - - name: ipsec_tunnel.TSr_port - type: long - description: > - TSr port of the IPsec tunnel - - name: ipsec_tunnel.proto - type: keyword - description: > - Protocol of the IPsec tunnel - - name: ipsec_tunnel.mode - type: keyword - description: > - This specifies the IPsec mode. e.g., 'tunl' - - name: ipsec_tunnel.dh - type: keyword - description: > - Diffie-Hellman group of the IPsec tunnel - - name: ipsec_tunnel.enc - type: keyword - description: > - Encryption algorithm of the IPsec tunnel - - name: ipsec_tunnel.hash - type: keyword - description: > - Hash algorithm of the IPsec tunnel - - name: ipsec_tunnel.life.sec - type: long - description: > - The lifetime of the IPsec Security Association (SA) in seconds - - name: ipsec_tunnel.kb - type: long - description: > - Traffic volume limit for SA rekeying \ No newline at end of file +- release: beta \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml index 06eaa7cfaec..05c31ead2f9 100644 --- a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml @@ -1,158 +1 @@ -- name: routing - type: group - release: beta - description: > - routing - fields: - - name: bgp.peer_name - type: keyword - description: > - The name of the current peer in the BGP peer group - - name: bgp.virtual_router - type: keyword - description: > - The virtual router with which the BGP peer is associated - - name: bgp.peer_group - type: keyword - description: > - The name of the BGP peer group this peer belongs to - - name: bgp.peer_router_id - type: ip - description: > - BGP peer router ID - - name: bgp.remote_as_asn - type: long - description: > - The remote Autonomous System (AS) number of the peer - - name: bgp.status - type: keyword - description: > - The BGP session status, e.g., "Established" means the session is up and running - - name: bgp.status_duration.sec - type: long - description: > - Time in seconds since the current status was set - - name: bgp.password_set - type: boolean - description: > - Indicates whether a password is set for the BGP peer - - name: bgp.passive - type: boolean - description: > - Indicates if the BGP peer is in passive mode: if yes then router will not initiate a connection to the peer - - name: bgp.multi_hop_ttl - type: long - description: > - Time to Live (TTL) value for multi-hop BGP sessions. Units are the number of hops. - - name: bgp.peer_ip - type: ip - description: > - IP address of the peer - - name: bgp.peer_port - type: long - description: > - Port number of the peer - - name: bgp.local_ip - type: ip - description: > - Local ip address used for BGP connection - - name: bgp.local_port - type: long - description: > - Local port number used for BGP connection - - name: bgp.reflector_client - type: keyword - description: > - Specifies the BGP peer relationship to route reflectors, e.g. "client", "not-client", "meshed-client" - - name: bgp.same_confederation - type: boolean - description: > - Peers in the same confederation exchange routes using internal BGP (iBGP) instead of external BGP (eBGP) - - name: bgp.aggregate_confed_as - type: boolean - description: > - Indicates that Autonomous System (AS) aggregation is enabled for the confederation - - name: bgp.peering_type - type: keyword - description: > - Defines the type of relationship between peers, e.g., "External BGP", "Internal BGP", or "Unspecified" - - name: bgp.connect_retry_interval.sec - type: long - description: > - The interval (in seconds) between connection retries - - name: bgp.open_delay.sec - type: long - description: > - Delay before sending an Open message (in seconds) - - name: bgp.idle_hold.sec - type: long - description: > - The idle hold time (in seconds) before retrying a connection after failure - - name: bgp.prefix_limit - type: long - description: > - The maximum number of prefixes that can be received from the peer (0 = no limit) - - name: bgp.holdtime.sec - type: long - description: > - Time in seconds that the BGP peer will wait for a keepalive message, negotiated between peers - - name: bgp.holdtime_config.sec - type: long - description: > - Represents the locally configured hold time on this peer (in seconds) - - name: bgp.keepalive.sec - type: long - description: > - The interval (in seconds) at which BGP keepalive messages are sent, negotiated between peers - - name: bgp.keepalive_config.sec - type: long - description: > - The keepalive configured on this peer - - name: bgp.msg_update_in.count - type: long - description: > - The number of BGP UPDATE messages received by the router from this peer - - name: bgp.msg_update_out.count - type: long - description: > - the number of BGP UPDATE messages sent from the local router to the peer - - name: bgp.msg_total_in.count - type: long - description: > - Total of all messages received from the peer - - name: bgp.msg_total_out.count - type: long - description: > - Total of all messages sent to the peer - - name: bgp.last_update_age.sec - type: long - description: > - Time in seconds since the last update message was received from the peer - - name: bgp.last_error - type: keyword - description: > - The last BGP error message received from the peer - - name: bgp.status_flap_counts - type: long - description: > - Indicates the number of times the BGP session has "flapped" or transitioned between up and down states - - name: bgp.established_counts - type: long - description: > - Number of times the BGP session has successfully transitioned to the "Established" state - - name: bgp.orf_entry_received - type: long - description: > - Number of ORF (Outbound Route Filtering) entries received from the peer - - name: bgp.nexthop_self - type: boolean - description: > - Whether the router is configured to use itself as the next-hop for routes sent to this peer - - name: bgp.nexthop_thirdparty - type: boolean - description: > - Third-party next-hop feature is enabled - - name: bgp.nexthop_peer - type: boolean - description: > - Indicates whether the peer is being used as the next-hop for the routes received from this peer \ No newline at end of file +- release: beta \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/system/_meta/fields.yml b/x-pack/metricbeat/module/panw/system/_meta/fields.yml index 9bb10e6f008..05c31ead2f9 100644 --- a/x-pack/metricbeat/module/panw/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/system/_meta/fields.yml @@ -1,297 +1 @@ -- name: system - type: group - release: beta - description: > - system - fields: - - name: uptime.days - type: integer - description: > - Uptime in days - - name: uptime.hours - type: integer - description: > - Hours component of uptime - - name: uptime.minutes - type: integer - description: > - Minutes component of uptime - - name: user_count - type: long - description: > - Number of users - - name: load_average.1m - type: float - description: > - Load average in 1 minute - - name: load_average.5m - type: float - description: > - Load average in 5 minutes - - name: load_average.15m - type: float - description: > - Load average in 15 minutes - - name: tasks.total - type: long - description: > - Total number of tasks - - name: tasks.running - type: long - description: > - Number of running tasks - - name: tasks.sleeping - type: long - description: > - Number of sleeping tasks - - name: tasks.stopped - type: long - description: > - Number of stopped tasks - - name: tasks.zombie - type: long - description: > - Number of zombie tasks - - name: cpu.user - type: float - description: > - CPU usage by user processes - - name: cpu.system - type: float - description: > - CPU usage by system processes - - name: cpu.nice - type: float - description: > - CPU usage by processes with a positive nice value - - name: cpu.idle - type: float - description: > - CPU idle time - - name: cpu.wait - type: float - description: > - CPU wait time - - name: cpu.hi - type: float - description: > - CPU hardware interrupts - - name: cpu.system_int - type: float - description: > - CPU software interrupts - - name: cpu.steal - type: float - description: > - CPU steal time - - name: memory.total - type: float - description: > - Total memory - - name: memory.free - type: float - description: > - Free memory - - name: memory.used - type: float - description: > - Used memory - - name: memory.buffer_cache - type: float - description: > - Memory used for buffers and cache - - name: swap.total - type: float - description: > - Total swap space - - name: swap.free - type: float - description: > - Free swap space - - name: swap.used - type: float - description: > - Used swap space - - name: swap.available - type: float - description: > - Available swap space - - name: license.feature - type: keyword - description: > - Feature licensed, e.g. Advanced Threat Prevention - - name: license.description - type: text - description: > - Description of the licensed feature - - name: license.serial - type: keyword - description: > - Serial number of license - - name: license.issued - type: date - description: > - Date the license was issued - - name: license.expires - type: date - description: > - Date the license expires - not set if license never expires - - name: license.never_expires - type: boolean - description: > - Indicates if the license never expires - - name: license.expired - type: boolean - description: > - Indicates if the license is expired - - name: license.auth_code - type: keyword - description: > - Authorization code to activate or install the license - - name: filesystem.name - type: keyword - description: > - Filesystem name - - name: filesystem.size - type: float - format: bytes - description: > - Total size of the filesystem - - name: filesystem.used - type: float - format: bytes - description: > - Amount used on the filesystem - - name: filesystem.available - type: float - format: bytes - description: > - Disk space available on the filesystem - - name: filesystem.use_percent - type: integer - format: percent - description: > - Percent of filesystem used - - name: filesystem.mounted - type: keyword - description: > - Filesystem mount point - - name: fan.slot_number - type: integer - description: > - The number of the hardware slot - - name: fan.description - type: keyword - description: > - The description of the fan - - name: fan.alarm - type: boolean - description: > - Is there an alarm status of the fan - - name: fan.rpm - type: integer - description: > - The speed of the fan in RPM - - name: fan.min_rpm - type: integer - description: > - The minimum speed of the fan in RPM - - name: thermal.slot_number - type: integer - description: > - Slot number field - - name: thermal.description - type: text - description: > - Description field - - name: thermal.alarm - type: boolean - description: > - Alarm field - - name: thermal.degrees_celsius - type: float - description: > - Degrees Celsius field - - name: thermal.minimum_temp - type: float - description: > - Minimum temperature field - - name: thermal.maximum_temp - type: float - description: > - Maximum temperature field - - name: power.slot_number - type: integer - description: > - Slot number field - - name: power.description - type: text - description: > - Description field - - name: power.alarm - type: boolean - description: > - Indicates if alarm is active - - name: power.volts - type: float - description: > - Current Volts - - name: power.minimum_volts - type: float - description: > - Minimum volts recorded - - name: power.maximum_volts - type: float - description: > - Maximum volts recorded - - name: certificate.issuer - type: keyword - description: > - issuer field - - - name: certificate.issuer_subject_hash - type: keyword - description: > - issuer_subject_hash field - - - name: certificate.issuer_key_hash - type: keyword - description: > - issuer_key_hash field - - - name: certificate.db_type - type: keyword - description: > - db_type field - - - name: certificate.db_exp_date - type: keyword - description: > - expiration date, format: 310329235959Z(Mar 29 23:59:59 2031 GMT) - - - name: certificate.db_rev_date - type: keyword - description: > - db_rev_date field - - - name: certificate.db_serial_no - type: keyword - description: > - db_serial_no field - - - name: certificate.db_file - type: keyword - description: > - db_file field - - - name: certificate.db_name - type: keyword - description: > - db_name field - - - name: certificate.db_status - type: keyword - description: > - db_status field - - +- release: beta \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml index 1a2e9e9eac9..05c31ead2f9 100644 --- a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml @@ -1,122 +1 @@ -- name: vpn - type: group - release: beta - description: > - vpn - fields: - - name: globalprotect.session.domain - type: keyword - description: > - Domain of the GlobalProtect session - - name: globalprotect.session.is_local - type: boolean - description: > - Indicates if the session is local - - name: globalprotect.session.username - type: keyword - description: > - Username of the session - - name: globalprotect.session.primary_username - type: keyword - description: > - Primary username of the session - - name: globalprotect.session.region_for_config - type: keyword - description: > - Region for configuration - - name: globalprotect.session.source_region - type: keyword - description: > - Source region of the session - - name: globalprotect.session.computer - type: keyword - description: > - Computer name in the session - - name: globalprotect.session.client - type: keyword - description: > - Client information of the session - - name: globalprotect.session.vpn_type - type: keyword - description: > - Type of VPN used in the session - - name: globalprotect.session.host_id - type: keyword - description: > - Host ID of the session - - name: globalprotect.session.app_version - type: keyword - description: > - Application version used in the session - - name: globalprotect.session.virtual_ip - type: ip - description: > - Virtual IP address of the session - - name: globalprotect.session.virtual_ipv6 - type: ip - description: > - Virtual IPv6 address of the session - - name: globalprotect.session.public_ip - type: ip - description: > - Public IP address of the session - - name: globalprotect.session.public_ipv6 - type: ip - description: > - Public IPv6 address of the session - - name: globalprotect.session.tunnel_type - type: keyword - description: > - Type of tunnel used in the session - - name: globalprotect.session.public_connection_ipv6 - type: ip - description: > - Public connection IPv6 address of the session - - name: globalprotect.session.client_ip - type: ip - description: > - Client IP address of the session - - name: globalprotect.session.login_time - type: date - description: > - Login time of the session - - name: globalprotect.session.login_time_utc - type: date - description: > - Login time in UTC of the session - - name: globalprotect.session.lifetime - type: long - description: > - Lifetime of the session - - name: globalprotect.session.request_login - type: keyword - description: > - Request login information of the session - - name: globalprotect.session.request_get_config - type: keyword - description: > - Request get configuration information of the session - - name: globalprotect.session.request_sslvpn_connect - type: keyword - description: > - Request SSL VPN connect information of the session - - name: globalprotect.gateway.name - type: keyword - description: > - Name of the GlobalProtect gateway - - name: globalprotect.gateway.current_users - type: long - description: > - Current number of users connected to the GlobalProtect gateway - - name: globalprotect.gateway.previous_users - type: long - description: > - Previous number of users connected to the GlobalProtect gateway - - name: globalprotect.total_current_users - type: long - description: > - Total current number of users connected to GlobalProtect gateway - - name: globalprotect.total_previous_users - type: long - description: > - Total previous number of users connected to GlobalProtect gateway +- release: beta \ No newline at end of file From e37b59d00214c445ad2d4983fed7c95f82bc515f Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Tue, 17 Sep 2024 16:39:44 +0530 Subject: [PATCH 27/32] make linter happy --- x-pack/metricbeat/module/panw/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/metricbeat/module/panw/client.go b/x-pack/metricbeat/module/panw/client.go index 6ac3161c148..4b670a89dce 100644 --- a/x-pack/metricbeat/module/panw/client.go +++ b/x-pack/metricbeat/module/panw/client.go @@ -17,7 +17,7 @@ const Vsys = "" // PanwClient interface with an Op function type PanwClient interface { - Op(req interface{}, vsys string, extras interface{}, ans interface{}) ([]byte, error) + Op(req interface{}, vsys string, extras, ans interface{}) ([]byte, error) } type PanwFirewallClient struct { From e833453de654e385a4544a7605068f2159a4e156 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Tue, 17 Sep 2024 18:10:48 +0530 Subject: [PATCH 28/32] add the untracked docs --- metricbeat/docs/modules/panw.asciidoc | 143 ++++++++++++++++++ .../docs/modules/panw/interfaces.asciidoc | 29 ++++ metricbeat/docs/modules/panw/routing.asciidoc | 29 ++++ metricbeat/docs/modules/panw/system.asciidoc | 29 ++++ metricbeat/docs/modules/panw/vpn.asciidoc | 29 ++++ 5 files changed, 259 insertions(+) create mode 100644 metricbeat/docs/modules/panw.asciidoc create mode 100644 metricbeat/docs/modules/panw/interfaces.asciidoc create mode 100644 metricbeat/docs/modules/panw/routing.asciidoc create mode 100644 metricbeat/docs/modules/panw/system.asciidoc create mode 100644 metricbeat/docs/modules/panw/vpn.asciidoc diff --git a/metricbeat/docs/modules/panw.asciidoc b/metricbeat/docs/modules/panw.asciidoc new file mode 100644 index 00000000000..c0166416501 --- /dev/null +++ b/metricbeat/docs/modules/panw.asciidoc @@ -0,0 +1,143 @@ +//// +This file is generated! See scripts/mage/docs_collector.go +//// + +:modulename: panw +:edit_url: https://github.com/elastic/beats/edit/main/x-pack/metricbeat/module/panw/_meta/docs.asciidoc + + +[[metricbeat-module-panw]] +[role="xpack"] +== Panw module + +beta[] + +:modulename: panw + +include::{libbeat-dir}/shared/integration-link.asciidoc[] + +:modulename!: + +The panw Metricbeat module uses the Palo Alto [pango](https://pkg.go.dev/github.com/PaloAltoNetworks/pango#section-documentation) package to extract metrics +information from a firewall device via the XML API. + +[float] +=== Dashboards + + +[float] +=== Module-specific configuration notes + +The panw module configuration requires the ip address of the target firewall device and an API Key generated from that firewall. It is assumed +that network access to the firewall is available. All access by the panw module is read-only. + +***Limitations*** +The current version of the module is configured to run against **exactly 1** firewall. Multiple firewalls will require multiple agent configurations. +The module has also not been tested with Panorama, though it should work since it only relies on lower level Client.Op calls to send XML API commands +to the server. + +Required credentials for the `panw` module: + +`host_ip` :: IP address of the firewall - must be network accessible. + +`apiKey`:: An API Key generated via an XML API call to the firewall or via the management dashboard. This + + +[float] +== Metricsets + +[float] +=== `bgp_peers` +This metricset reports information on BGP Peers defined in the firewall. + +[float] +=== `certificates` +This metricset will capture certificates defined on the firewall including expiration dates. + +[float] +=== `fans` +This metricset will collect information from hardware fans (RPMS) and will report if an alarm is active for a given fan. + +[float] +=== `filesystem` +This metricset reports disk usage for filesystems defined on the device, based on df output. + +[float] +=== `globalprotect_sessions` +This metricset will collect metrics on current user sessions established on Global Protect gateways. + +[float] +=== `globalprotect_stats` +This metricset reports the number of user per GlobalProtect gateway and totals across all gateways. + +[float] +=== `ha_interfaces` +This metricset will collect metrics from the device on High Availabilty configuration for interfaces. + +[float] +=== `licenses` +This metricset reports on licenses for sofware features with expiration dates. + +[float] +=== `logical` +This metricset will collect metrics on logical interfaces in the device's network. + +[float] +=== `power` +This metricset reports power usage and alarms. + +[float] +=== `system` +This metricset captures system informate such as uptime, user count, CPU, memory and swap: essentiallyl the first 5 lines of 'top' output. + +[float] +=== `temperature` +This metricset reports temperature for various slots on the device and reports on alarm status. + +[float] +=== `tunnels` +This metricset enumerates ipsec tunnels and their status. + + + +:edit_url: + +[float] +=== Example configuration + +The Panw module supports the standard configuration options that are described +in <>. Here is an example configuration: + +[source,yaml] +---- +metricbeat.modules: +- module: panw + metricsets: ["licenses"] + enabled: false + period: 10s + hosts: ["localhost"] + +---- + +[float] +=== Metricsets + +The following metricsets are available: + +* <> + +* <> + +* <> + +* <> + +include::panw/interfaces.asciidoc[] + +include::panw/routing.asciidoc[] + +include::panw/system.asciidoc[] + +include::panw/vpn.asciidoc[] + +:edit_url!: diff --git a/metricbeat/docs/modules/panw/interfaces.asciidoc b/metricbeat/docs/modules/panw/interfaces.asciidoc new file mode 100644 index 00000000000..6012964a55c --- /dev/null +++ b/metricbeat/docs/modules/panw/interfaces.asciidoc @@ -0,0 +1,29 @@ +//// +This file is generated! See scripts/mage/docs_collector.go +//// +:edit_url: https://github.com/elastic/beats/edit/main/x-pack/metricbeat/module/panw/interfaces/_meta/docs.asciidoc + + +[[metricbeat-metricset-panw-interfaces]] +[role="xpack"] +=== Panw interfaces metricset + +beta[] + +include::../../../../x-pack/metricbeat/module/panw/interfaces/_meta/docs.asciidoc[] + + +:edit_url: + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../../x-pack/metricbeat/module/panw/interfaces/_meta/data.json[] +---- +:edit_url!: \ No newline at end of file diff --git a/metricbeat/docs/modules/panw/routing.asciidoc b/metricbeat/docs/modules/panw/routing.asciidoc new file mode 100644 index 00000000000..3bcaf07fa40 --- /dev/null +++ b/metricbeat/docs/modules/panw/routing.asciidoc @@ -0,0 +1,29 @@ +//// +This file is generated! See scripts/mage/docs_collector.go +//// +:edit_url: https://github.com/elastic/beats/edit/main/x-pack/metricbeat/module/panw/routing/_meta/docs.asciidoc + + +[[metricbeat-metricset-panw-routing]] +[role="xpack"] +=== Panw routing metricset + +beta[] + +include::../../../../x-pack/metricbeat/module/panw/routing/_meta/docs.asciidoc[] + + +:edit_url: + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../../x-pack/metricbeat/module/panw/routing/_meta/data.json[] +---- +:edit_url!: \ No newline at end of file diff --git a/metricbeat/docs/modules/panw/system.asciidoc b/metricbeat/docs/modules/panw/system.asciidoc new file mode 100644 index 00000000000..ad159dffe42 --- /dev/null +++ b/metricbeat/docs/modules/panw/system.asciidoc @@ -0,0 +1,29 @@ +//// +This file is generated! See scripts/mage/docs_collector.go +//// +:edit_url: https://github.com/elastic/beats/edit/main/x-pack/metricbeat/module/panw/system/_meta/docs.asciidoc + + +[[metricbeat-metricset-panw-system]] +[role="xpack"] +=== Panw system metricset + +beta[] + +include::../../../../x-pack/metricbeat/module/panw/system/_meta/docs.asciidoc[] + + +:edit_url: + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../../x-pack/metricbeat/module/panw/system/_meta/data.json[] +---- +:edit_url!: \ No newline at end of file diff --git a/metricbeat/docs/modules/panw/vpn.asciidoc b/metricbeat/docs/modules/panw/vpn.asciidoc new file mode 100644 index 00000000000..b1d9e9df0dd --- /dev/null +++ b/metricbeat/docs/modules/panw/vpn.asciidoc @@ -0,0 +1,29 @@ +//// +This file is generated! See scripts/mage/docs_collector.go +//// +:edit_url: https://github.com/elastic/beats/edit/main/x-pack/metricbeat/module/panw/vpn/_meta/docs.asciidoc + + +[[metricbeat-metricset-panw-vpn]] +[role="xpack"] +=== Panw vpn metricset + +beta[] + +include::../../../../x-pack/metricbeat/module/panw/vpn/_meta/docs.asciidoc[] + + +:edit_url: + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../../x-pack/metricbeat/module/panw/vpn/_meta/data.json[] +---- +:edit_url!: \ No newline at end of file From 1d55a220fee527783a14252fdfda1bab42e4d6ff Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Tue, 17 Sep 2024 18:58:56 +0530 Subject: [PATCH 29/32] update the fields.yml --- x-pack/metricbeat/module/panw/fields.go | 2 +- x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml | 4 +++- x-pack/metricbeat/module/panw/routing/_meta/fields.yml | 4 +++- x-pack/metricbeat/module/panw/system/_meta/fields.yml | 4 +++- x-pack/metricbeat/module/panw/vpn/_meta/fields.yml | 4 +++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/x-pack/metricbeat/module/panw/fields.go b/x-pack/metricbeat/module/panw/fields.go index d5044241669..77991702838 100644 --- a/x-pack/metricbeat/module/panw/fields.go +++ b/x-pack/metricbeat/module/panw/fields.go @@ -19,5 +19,5 @@ func init() { // AssetPanw returns asset data. // This is the base64 encoded zlib format compressed contents of module/panw. func AssetPanw() string { - return "eJyszUEKwjAUhOF9TjF0nwu8nRfQgid4mlGCaRKSV0pvL0URceGqs/wX33g8uAqq5sUBFi1RMIyal8EBgf3aYrVYsmA8HP3pjKmEOdEBjYnaKbjQ1AG3yBS6OADwyDrx426ztVJwb2Wu7/JX3/YtvtTfz336MwAA//80X0nz" + return "eJykzkEKgzAQheF9TvFw7wWy6wVaoSdI9SmhcRKSseLti1DEllIo/ssZ+Hg17lwskpPZAOo10KJqnMyVATqWNvukPopFczrXlyvG2E2BBsgMdIUWN6ozQO8ZumINANQQN3Jz13RJtBhynNLr8lNf24t71Ysy965l2V7f/LXPke9QjpN6GQ4qZSnK8SDySPKn8AwAAP//aSl4eA==" } diff --git a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml index 05c31ead2f9..16df26b4da7 100644 --- a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml @@ -1 +1,3 @@ -- release: beta \ No newline at end of file +- name: interfaces + type: group + release: beta \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml index 05c31ead2f9..f4009cae0c2 100644 --- a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml @@ -1 +1,3 @@ -- release: beta \ No newline at end of file +- name: routing + type: group + release: beta \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/system/_meta/fields.yml b/x-pack/metricbeat/module/panw/system/_meta/fields.yml index 05c31ead2f9..c76e96c2b81 100644 --- a/x-pack/metricbeat/module/panw/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/system/_meta/fields.yml @@ -1 +1,3 @@ -- release: beta \ No newline at end of file +- name: system + type: group + release: beta \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml index 05c31ead2f9..d1a9d2f32f0 100644 --- a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml @@ -1 +1,3 @@ -- release: beta \ No newline at end of file +- name: vpn + type: group + release: beta \ No newline at end of file From 77ba48ed36889ed61f3a15e836f81635c6e0e958 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Tue, 17 Sep 2024 20:27:24 +0530 Subject: [PATCH 30/32] update the fields.yml with example fields to make python integ tests happy --- x-pack/metricbeat/module/panw/fields.go | 2 +- x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml | 6 +++++- x-pack/metricbeat/module/panw/routing/_meta/fields.yml | 6 +++++- x-pack/metricbeat/module/panw/system/_meta/fields.yml | 6 +++++- x-pack/metricbeat/module/panw/vpn/_meta/fields.yml | 6 +++++- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/x-pack/metricbeat/module/panw/fields.go b/x-pack/metricbeat/module/panw/fields.go index 77991702838..c63f4af7486 100644 --- a/x-pack/metricbeat/module/panw/fields.go +++ b/x-pack/metricbeat/module/panw/fields.go @@ -19,5 +19,5 @@ func init() { // AssetPanw returns asset data. // This is the base64 encoded zlib format compressed contents of module/panw. func AssetPanw() string { - return "eJykzkEKgzAQheF9TvFw7wWy6wVaoSdI9SmhcRKSseLti1DEllIo/ssZ+Hg17lwskpPZAOo10KJqnMyVATqWNvukPopFczrXlyvG2E2BBsgMdIUWN6ozQO8ZumINANQQN3Jz13RJtBhynNLr8lNf24t71Ysy965l2V7f/LXPke9QjpN6GQ4qZSnK8SDySPKn8AwAAP//aSl4eA==" + return "eJzUz0FOBCEQheE9p3iZfV+AnRfQSTwBDm8mZKAgUNhye9NGO21rXNtvSSVffibcOSyKk9kAGjTS4nR2Mp8M4NkuNRQNWSzOD4/T0zNS9j3SAJWRrtHiheoMcA2MvlkDABPEJa7uMh2FFreae/l8+VNfthW3ahBlvboL23r6zV+2j/zant7yfHOprBHf/TvHnKvf3XxIlPbxD62dP4Jr7hrkdpDaNpoyHST2tcg/LX0PAAD//4Q63bA=" } diff --git a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml index 16df26b4da7..7e7dacf152c 100644 --- a/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/interfaces/_meta/fields.yml @@ -1,3 +1,7 @@ - name: interfaces type: group - release: beta \ No newline at end of file + release: beta + fields: + - name: example + type: keyword + dimension: true \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml index f4009cae0c2..98c9cba48a3 100644 --- a/x-pack/metricbeat/module/panw/routing/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/routing/_meta/fields.yml @@ -1,3 +1,7 @@ - name: routing type: group - release: beta \ No newline at end of file + release: beta + fields: + - name: example + type: keyword + dimension: true \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/system/_meta/fields.yml b/x-pack/metricbeat/module/panw/system/_meta/fields.yml index c76e96c2b81..87e8b542706 100644 --- a/x-pack/metricbeat/module/panw/system/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/system/_meta/fields.yml @@ -1,3 +1,7 @@ - name: system type: group - release: beta \ No newline at end of file + release: beta + fields: + - name: example + type: keyword + dimension: true \ No newline at end of file diff --git a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml index d1a9d2f32f0..f6730c0a956 100644 --- a/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml +++ b/x-pack/metricbeat/module/panw/vpn/_meta/fields.yml @@ -1,3 +1,7 @@ - name: vpn type: group - release: beta \ No newline at end of file + release: beta + fields: + - name: example + type: keyword + dimension: true \ No newline at end of file From d51944e58b6abf303848d7c3edce05ae380cb8b2 Mon Sep 17 00:00:00 2001 From: subham sarkar Date: Tue, 17 Sep 2024 20:45:05 +0530 Subject: [PATCH 31/32] make docs check happy and update codeowners --- .github/CODEOWNERS | 1 + metricbeat/docs/fields.asciidoc | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 90473951d9f..de5f2325dd4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -219,6 +219,7 @@ CHANGELOG* /x-pack/metricbeat/module/istio/ @elastic/obs-cloudnative-monitoring /x-pack/metricbeat/module/mssql @elastic/obs-infraobs-integrations /x-pack/metricbeat/module/oracle @elastic/obs-infraobs-integrations +/x-pack/metricbeat/module/panw @elastic/obs-infraobs-integrations /x-pack/metricbeat/module/prometheus/ @elastic/obs-cloudnative-monitoring /x-pack/metricbeat/module/redisenterprise @elastic/obs-infraobs-integrations /x-pack/metricbeat/module/sql @elastic/obs-infraobs-integrations diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 03fa5ae1156..c171067bfe2 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -57153,6 +57153,38 @@ PAN-OS module PAN-OS module + +*`panw.interfaces.example`*:: ++ +-- +type: keyword + +-- + + +*`panw.routing.example`*:: ++ +-- +type: keyword + +-- + + +*`panw.system.example`*:: ++ +-- +type: keyword + +-- + + +*`panw.vpn.example`*:: ++ +-- +type: keyword + +-- + [[exported-fields-php_fpm]] == PHP_FPM fields From 87e57f514304561f2f9de836f5f930dfa1fbadd5 Mon Sep 17 00:00:00 2001 From: tommyers-elastic <106530686+tommyers-elastic@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:41:18 +0100 Subject: [PATCH 32/32] add result of 'mage update' in x-pack/metricbeat --- x-pack/metricbeat/metricbeat.reference.yml | 68 +++++++++++----------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/x-pack/metricbeat/metricbeat.reference.yml b/x-pack/metricbeat/metricbeat.reference.yml index 4e0c65553ec..8ab17c6c44c 100644 --- a/x-pack/metricbeat/metricbeat.reference.yml +++ b/x-pack/metricbeat/metricbeat.reference.yml @@ -1327,11 +1327,9 @@ metricbeat.modules: # Password to use when connecting to PostgreSQL. Empty by default. #password: pass -#------------------------------ Prometheus Module ------------------------------ -# Metrics collected from a Prometheus endpoint +#----------------------- Prometheus Typed Metrics Module ----------------------- - module: prometheus period: 10s - metricsets: ["collector"] hosts: ["localhost:9090"] metrics_path: /metrics #metrics_filters: @@ -1340,14 +1338,20 @@ metricbeat.modules: #username: "user" #password: "secret" - # Count number of metrics present in Elasticsearch document (default: false) - #metrics_count: false - # This can be used for service account based authorization: #bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token #ssl.certificate_authorities: # - /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt + # Count number of metrics present in Elasticsearch document (default: false) + #metrics_count: false + + # Use Elasticsearch histogram type to store histograms (beta, default: false) + # This will change the default layout and put metric type in the field name + #use_types: true + + # Store counter rates instead of original cumulative counters (experimental, default: false) + #rate_counters: true # Metrics sent by a Prometheus server using remote_write option #- module: prometheus @@ -1355,13 +1359,25 @@ metricbeat.modules: # host: "localhost" # port: "9201" - # Count number of metrics present in Elasticsearch document (default: false) - #metrics_count: false - # Secure settings for the server using TLS/SSL: #ssl.certificate: "/etc/pki/server/cert.pem" #ssl.key: "/etc/pki/server/cert.key" + # Count number of metrics present in Elasticsearch document (default: false) + #metrics_count: false + + # Use Elasticsearch histogram type to store histograms (beta, default: false) + # This will change the default layout and put metric type in the field name + #use_types: true + + # Store counter rates instead of original cumulative counters (experimental, default: false) + #rate_counters: true + + # Define patterns for counter and histogram types so as to identify metrics' types according to these patterns + #types_patterns: + # counter_patterns: [] + # histogram_patterns: [] + # Metrics that will be collected using a PromQL #- module: prometheus # metricsets: ["query"] @@ -1388,9 +1404,11 @@ metricbeat.modules: # params: # query: "some_value" -#----------------------- Prometheus Typed Metrics Module ----------------------- +#------------------------------ Prometheus Module ------------------------------ +# Metrics collected from a Prometheus endpoint - module: prometheus period: 10s + metricsets: ["collector"] hosts: ["localhost:9090"] metrics_path: /metrics #metrics_filters: @@ -1399,20 +1417,14 @@ metricbeat.modules: #username: "user" #password: "secret" + # Count number of metrics present in Elasticsearch document (default: false) + #metrics_count: false + # This can be used for service account based authorization: #bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token #ssl.certificate_authorities: # - /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt - # Count number of metrics present in Elasticsearch document (default: false) - #metrics_count: false - - # Use Elasticsearch histogram type to store histograms (beta, default: false) - # This will change the default layout and put metric type in the field name - #use_types: true - - # Store counter rates instead of original cumulative counters (experimental, default: false) - #rate_counters: true # Metrics sent by a Prometheus server using remote_write option #- module: prometheus @@ -1420,24 +1432,12 @@ metricbeat.modules: # host: "localhost" # port: "9201" - # Secure settings for the server using TLS/SSL: - #ssl.certificate: "/etc/pki/server/cert.pem" - #ssl.key: "/etc/pki/server/cert.key" - # Count number of metrics present in Elasticsearch document (default: false) #metrics_count: false - # Use Elasticsearch histogram type to store histograms (beta, default: false) - # This will change the default layout and put metric type in the field name - #use_types: true - - # Store counter rates instead of original cumulative counters (experimental, default: false) - #rate_counters: true - - # Define patterns for counter and histogram types so as to identify metrics' types according to these patterns - #types_patterns: - # counter_patterns: [] - # histogram_patterns: [] + # Secure settings for the server using TLS/SSL: + #ssl.certificate: "/etc/pki/server/cert.pem" + #ssl.key: "/etc/pki/server/cert.key" # Metrics that will be collected using a PromQL #- module: prometheus