diff --git a/README.md b/README.md old mode 100755 new mode 100644 index 7adb852e..0848f2dc --- a/README.md +++ b/README.md @@ -108,6 +108,10 @@ Per-VDOM: * _System/SDNConnector_ * `fortigate_system_sdn_connector_status` * `fortigate_system_sdn_connector_last_update_seconds` + * _/System/CentralManagement/Status_ + * `fortigate_system_central_management_mode` + * `fortigate_system_central_management_status` + * `fortigate_system_central_management_registration_status` * _System/VDOMResource_ * `fortigate_vdom_resource_cpu_usage` * `fortigate_vdom_resource_memory_usage` @@ -444,11 +448,13 @@ To improve security, limit permissions to required ones only (least privilege pr |Log/DiskUsage | loggrp.config |api/v2/monitor/log/current-disk-usage | |Network/Dns/Latency | sysgrp.cfg |api/v2/monitor/network/dns/latency | |System/AvailableCertificates | *any* |api/v2/monitor/system/available-certificates | +|System/Central-management/Status | sysgrp.cfg |api/v2/monitor/system/central-management/status| |System/Fortimanager/Status | sysgrp.cfg |api/v2/monitor/system/fortimanager/status | |System/HAStatistics | sysgrp.cfg |api/v2/monitor/system/ha-statistics
api/v2/cmdb/system/ha | |System/Interface | netgrp.cfg |api/v2/monitor/system/interface/select | |System/Interface/Transceivers| *any* |api/v2/monitor/system/interface/transceivers | |System/LinkMonitor | sysgrp.cfg |api/v2/monitor/system/link-monitor | +|System/Performance/Status | sysgrp.cfg |api/v2/monitor/system/performance/status | |System/Ntp/Status | netgrp.cfg |api/v2/monitor/system/ntp/status | |System/Resource/Usage | sysgrp.cfg |api/v2/monitor/system/resource/usage | |System/Resource/Usage/VDOM | sysgrp.cfg |api/v2/monitor/system/resource/usage | diff --git a/pkg/probe/probe.go b/pkg/probe/probe.go index 81157e16..a1bb4e55 100644 --- a/pkg/probe/probe.go +++ b/pkg/probe/probe.go @@ -145,6 +145,7 @@ func (p *Collector) Probe(ctx context.Context, target map[string]string, hc *htt {"Log/DiskUsage", probeLogCurrentDiskUsage}, {"Network/Dns/Latency", probeNetworkDNSLatency}, {"System/AvailableCertificates", probeSystemAvailableCertificates}, + {"System/Central-Management/Status", probeSystemCentralManagementStatus}, {"System/Fortimanager/Status", probeSystemFortimanagerStatus}, {"System/HAStatistics", probeSystemHAStatistics}, {"System/Interface", probeSystemInterface}, diff --git a/pkg/probe/system_central_management.go b/pkg/probe/system_central_management.go new file mode 100644 index 00000000..b123d824 --- /dev/null +++ b/pkg/probe/system_central_management.go @@ -0,0 +1,101 @@ +// Copyright 2025 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package probe + +import ( + "log" + "strconv" + + "github.com/prometheus/client_golang/prometheus" + + "github.com/prometheus-community/fortigate_exporter/pkg/http" +) + +func probeSystemCentralManagementStatus(c http.FortiHTTP, _ *TargetMetadata) ([]prometheus.Metric, bool) { + var ( + mode = prometheus.NewDesc( + "fortigate_system_central_management_mode", + "Operating mode of the central management.", + []string{"mode", "server", "mgmt_ip", "mgmt_port", "sn", "pendfortman"}, nil, + ) + status = prometheus.NewDesc( + "fortigate_system_central_management_status", + "Status of the connection from FortiGate to the central management server.", + []string{"status", "server", "mgmt_ip", "mgmt_port", "sn", "pendfortman"}, nil, + ) + registrationStatus = prometheus.NewDesc( + "fortigate_system_central_management_registration_status", + "Status of the registration from FortiGate to the central management server.", + []string{"status", "server", "mgmt_ip", "mgmt_port", "sn", "pendfortman"}, nil, + ) + ) + + type centralManagementStatus struct { + Mode string `json:"mode"` + Server string `json:"server"` + Status string `json:"status"` + RegStat string `json:"registration_status"` + MgmtIP string `json:"mgmt_ip"` + MgmtPort float64 `json:"mgmt_port"` + Sn string `json:"sn"` + PenFortMan string `json:"pending_fortimanager"` + } + + type centralManagementStatusResult struct { + Result centralManagementStatus `json:"results"` + } + + var res centralManagementStatusResult + if err := c.Get("api/v2/monitor/system/central-management/status", "skip_detect=true", &res); err != nil { + log.Printf("Error: %v", err) + return nil, false + } + + m := []prometheus.Metric{} + var normal, backup, down, up, handshake, inProgress, registered, unregistered, defaultValue float64 + if res.Result.Mode == "normal" { + normal = 1 + } else { + backup = 1 + } + switch res.Result.Status { + case "down": + down = 1 + case "up": + up = 1 + case "handshake": + handshake = 1 + } + switch res.Result.RegStat { + case "in_progress": + inProgress = 1 + case "registered": + registered = 1 + case "unregistered": + unregistered = 1 + default: + defaultValue = 1 + } + m = append(m, prometheus.MustNewConstMetric(mode, prometheus.GaugeValue, normal, "normal", res.Result.Server, res.Result.MgmtIP, strconv.FormatFloat(res.Result.MgmtPort, 'f', -1, 64), res.Result.Sn, res.Result.PenFortMan)) + m = append(m, prometheus.MustNewConstMetric(mode, prometheus.GaugeValue, backup, "backup", res.Result.Server, res.Result.MgmtIP, strconv.FormatFloat(res.Result.MgmtPort, 'f', -1, 64), res.Result.Sn, res.Result.PenFortMan)) + m = append(m, prometheus.MustNewConstMetric(status, prometheus.GaugeValue, down, "down", res.Result.Server, res.Result.MgmtIP, strconv.FormatFloat(res.Result.MgmtPort, 'f', -1, 64), res.Result.Sn, res.Result.PenFortMan)) + m = append(m, prometheus.MustNewConstMetric(status, prometheus.GaugeValue, up, "up", res.Result.Server, res.Result.MgmtIP, strconv.FormatFloat(res.Result.MgmtPort, 'f', -1, 64), res.Result.Sn, res.Result.PenFortMan)) + m = append(m, prometheus.MustNewConstMetric(status, prometheus.GaugeValue, handshake, "handshake", res.Result.Server, res.Result.MgmtIP, strconv.FormatFloat(res.Result.MgmtPort, 'f', -1, 64), res.Result.Sn, res.Result.PenFortMan)) + m = append(m, prometheus.MustNewConstMetric(registrationStatus, prometheus.GaugeValue, inProgress, "inprogress", res.Result.Server, res.Result.MgmtIP, strconv.FormatFloat(res.Result.MgmtPort, 'f', -1, 64), res.Result.Sn, res.Result.PenFortMan)) + m = append(m, prometheus.MustNewConstMetric(registrationStatus, prometheus.GaugeValue, registered, "registered", res.Result.Server, res.Result.MgmtIP, strconv.FormatFloat(res.Result.MgmtPort, 'f', -1, 64), res.Result.Sn, res.Result.PenFortMan)) + m = append(m, prometheus.MustNewConstMetric(registrationStatus, prometheus.GaugeValue, unregistered, "unregistered", res.Result.Server, res.Result.MgmtIP, strconv.FormatFloat(res.Result.MgmtPort, 'f', -1, 64), res.Result.Sn, res.Result.PenFortMan)) + m = append(m, prometheus.MustNewConstMetric(registrationStatus, prometheus.GaugeValue, defaultValue, "unknown", res.Result.Server, res.Result.MgmtIP, strconv.FormatFloat(res.Result.MgmtPort, 'f', -1, 64), res.Result.Sn, res.Result.PenFortMan)) + + return m, true +} diff --git a/pkg/probe/system_central_management_test.go b/pkg/probe/system_central_management_test.go new file mode 100644 index 00000000..bf39286b --- /dev/null +++ b/pkg/probe/system_central_management_test.go @@ -0,0 +1,52 @@ +// Copyright 2025 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package probe + +import ( + "strings" + "testing" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" +) + +func TestSystemCentralManagementStatus(t *testing.T) { + c := newFakeClient() + c.prepare("api/v2/monitor/system/central-management/status", "testdata/system-central-management-status.jsonnet") + r := prometheus.NewPedanticRegistry() + if !testProbe(probeSystemCentralManagementStatus, c, r) { + t.Errorf("probeSystemCentralManagementStatus() returned non-success") + } + + em := `# HELP fortigate_system_central_management_mode Operating mode of the central management. +# TYPE fortigate_system_central_management_mode gauge +fortigate_system_central_management_mode{mgmt_ip="127.0.0.1",mgmt_port="0",mode="backup",pendfortman="12.329845.45k3",server="HA-TEST",sn="121748"} 0 +fortigate_system_central_management_mode{mgmt_ip="127.0.0.1",mgmt_port="0",mode="normal",pendfortman="12.329845.45k3",server="HA-TEST",sn="121748"} 1 +# HELP fortigate_system_central_management_registration_status Status of the registration from FortiGate to the central management server. +# TYPE fortigate_system_central_management_registration_status gauge +fortigate_system_central_management_registration_status{mgmt_ip="127.0.0.1",mgmt_port="0",pendfortman="12.329845.45k3",server="HA-TEST",sn="121748",status="inprogress"} 0 +fortigate_system_central_management_registration_status{mgmt_ip="127.0.0.1",mgmt_port="0",pendfortman="12.329845.45k3",server="HA-TEST",sn="121748",status="registered"} 0 +fortigate_system_central_management_registration_status{mgmt_ip="127.0.0.1",mgmt_port="0",pendfortman="12.329845.45k3",server="HA-TEST",sn="121748",status="unknown"} 1 +fortigate_system_central_management_registration_status{mgmt_ip="127.0.0.1",mgmt_port="0",pendfortman="12.329845.45k3",server="HA-TEST",sn="121748",status="unregistered"} 0 +# HELP fortigate_system_central_management_status Status of the connection from FortiGate to the central management server. +# TYPE fortigate_system_central_management_status gauge +fortigate_system_central_management_status{mgmt_ip="127.0.0.1",mgmt_port="0",pendfortman="12.329845.45k3",server="HA-TEST",sn="121748",status="down"} 1 +fortigate_system_central_management_status{mgmt_ip="127.0.0.1",mgmt_port="0",pendfortman="12.329845.45k3",server="HA-TEST",sn="121748",status="handshake"} 0 +fortigate_system_central_management_status{mgmt_ip="127.0.0.1",mgmt_port="0",pendfortman="12.329845.45k3",server="HA-TEST",sn="121748",status="up"} 0 +` + + if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil { + t.Fatalf("metric compare: err %v", err) + } +} diff --git a/pkg/probe/testdata/system-central-management-status.jsonnet b/pkg/probe/testdata/system-central-management-status.jsonnet new file mode 100644 index 00000000..35ddd606 --- /dev/null +++ b/pkg/probe/testdata/system-central-management-status.jsonnet @@ -0,0 +1,21 @@ +{ + "http_method":"GET", + "results":{ + "mode": "normal", + "server": "HA-TEST", + "status": "down", + "registration_status": "unknown", + "mgmt_ip": "127.0.0.1", + "mgmt_port": 0, + "sn": "121748", + "pending_fortimanager": "12.329845.45k3" + }, + "vdom":"root", + "path":"system", + "name":"fortimanager", + "action":"status", + "status":"success", + "serial":"FGT61FT000000000", + "version":"v6.0.10", + "build":365 +} \ No newline at end of file