Skip to content

Commit

Permalink
[feat] CentralManagement Status metrics. Replaces Fortimanager Status…
Browse files Browse the repository at this point in the history
… which is deprecated in FortiOS 7.6+
  • Loading branch information
Joel Norberg committed Oct 11, 2024
1 parent 2aaf029 commit 96ec047
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ Per-VDOM:
* _System/Fortimanager/Status_
* `fortigate_fortimanager_connection_status`
* `fortigate_fortimanager_registration_status`
* _System/CentralManagement/Status_
* `fortigate_central_management_connection_status`
* `fortigate_central_management_status`
* _System/Interface_
* `fortigate_interface_link_up`
* `fortigate_interface_speed_bps`
Expand Down
1 change: 1 addition & 0 deletions pkg/probe/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ func (p *ProbeCollector) Probe(ctx context.Context, target map[string]string, hc
{"Log/DiskUsage", probeLogCurrentDiskUsage},
{"System/AvailableCertificates", probeSystemAvailableCertificates},
{"System/Fortimanager/Status", probeSystemFortimanagerStatus},
{"System/CentralManagement/Status", probeSystemCentralManagementStatus},
{"System/HAStatistics", probeSystemHAStatistics},
{"System/Interface", probeSystemInterface},
{"System/LinkMonitor", probeSystemLinkMonitor},
Expand Down
88 changes: 88 additions & 0 deletions pkg/probe/system_central_management.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package probe

import (
"log"

"github.com/bluecmd/fortigate_exporter/pkg/http"
"github.com/prometheus/client_golang/prometheus"
)

type SystemCentralManagementResults struct {
Mode string `json:"mode"`
Status string `json:"status"`
Registration string `json:"registration_status"`
}

type SystemCentralManagementStatus struct {
Results SystemCentralManagementResults `json:"results"`
VDOM string `json:"vdom"`
}

func probeSystemCentralManagementStatus(c http.FortiHTTP, meta *TargetMetadata) ([]prometheus.Metric, bool) {
// New API in FortiOS v7.4.0+
if meta.VersionMajor < 7 || (meta.VersionMajor == 7 && meta.VersionMinor < 4) {
log.Printf("Unsupported probe System/CentralManagement/Status - requires minimum FortiOS v7.4.0")
return []prometheus.Metric{}, false
}
var (
FortimanStat_id = prometheus.NewDesc(
"fortigate_central_management_connection_status",
"Fortimanager status",
[]string{"vdom", "mode", "status"}, nil,
)
FortimanReg_id = prometheus.NewDesc(
"fortigate_central_management_registration_status",
"Fortimanager registration status",
[]string{"vdom", "mode", "status"}, nil,
)
)

var res []SystemCentralManagementStatus
if err := c.Get("api/v2/monitor/system/central-management/status", "vdom=*", &res); err != nil {
log.Printf("Error: %v", err)
return nil, false
}

m := []prometheus.Metric{}
for _, r := range res {
StatusDown, StatusHandshake, StatusUp := 0.0, 0.0, 0.0
switch r.Results.Status {
case "down":
// No management Tunnel
StatusDown = 1.0
case "handshake":
// Management tunnel establishment in progress
StatusHandshake = 1.0
case "up":
// Management tunnel is establised
StatusUp = 1.0
}

RegistrationUnknown, RegistrationInProgress, RegistrationRegistered, RegistrationUnregistered := 0.0, 0.0, 0.0, 0.0
switch r.Results.Registration {
case "unknown":
// FMG does not know about the device
RegistrationUnknown = 1.0
case "in_progress":
// FMG does know the device, but it is not yet fully saved in the list of unregistered devices
RegistrationInProgress = 1.0
case "registered":
// FMG does know the device, and device is authorized
RegistrationRegistered = 1.0
case "unregistered ":
// FMG does know the device, but it is not yet authorized
RegistrationUnregistered = 1.0
}

m = append(m, prometheus.MustNewConstMetric(FortimanStat_id, prometheus.GaugeValue, StatusDown, r.VDOM, r.Results.Mode, "down"))
m = append(m, prometheus.MustNewConstMetric(FortimanStat_id, prometheus.GaugeValue, StatusHandshake, r.VDOM, r.Results.Mode, "handshake"))
m = append(m, prometheus.MustNewConstMetric(FortimanStat_id, prometheus.GaugeValue, StatusUp, r.VDOM, r.Results.Mode, "up"))

m = append(m, prometheus.MustNewConstMetric(FortimanReg_id, prometheus.GaugeValue, RegistrationUnknown, r.VDOM, r.Results.Mode, "unknown"))
m = append(m, prometheus.MustNewConstMetric(FortimanReg_id, prometheus.GaugeValue, RegistrationInProgress, r.VDOM, r.Results.Mode, "inprogress"))
m = append(m, prometheus.MustNewConstMetric(FortimanReg_id, prometheus.GaugeValue, RegistrationRegistered, r.VDOM, r.Results.Mode, "registered"))
m = append(m, prometheus.MustNewConstMetric(FortimanReg_id, prometheus.GaugeValue, RegistrationUnregistered, r.VDOM, r.Results.Mode, "unregistered"))
}

return m, true
}
47 changes: 47 additions & 0 deletions pkg/probe/system_central_management_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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()
meta := &TargetMetadata{
VersionMajor: 7,
VersionMinor: 4,
}
if !testProbeWithMetadata(probeSystemCentralManagementStatus, c, meta, r) {
t.Errorf("probeSystemCentralManagementStatus() returned non-success")
}

em := `
# HELP fortigate_central_management_connection_status Fortimanager status
# TYPE fortigate_central_management_connection_status gauge
fortigate_central_management_connection_status{mode="",status="down",vdom="test1"} 0
fortigate_central_management_connection_status{mode="",status="down",vdom="root"} 0
fortigate_central_management_connection_status{mode="",status="handshake",vdom="test1"} 1
fortigate_central_management_connection_status{mode="",status="handshake",vdom="root"} 0
fortigate_central_management_connection_status{mode="",status="up",vdom="test1"} 0
fortigate_central_management_connection_status{mode="",status="up",vdom="root"} 1
# HELP fortigate_central_management_registration_status Fortimanager registration status
# TYPE fortigate_central_management_registration_status gauge
fortigate_central_management_registration_status{mode="",status="inprogress",vdom="test1"} 0
fortigate_central_management_registration_status{mode="",status="inprogress",vdom="root"} 0
fortigate_central_management_registration_status{mode="",status="registered",vdom="test1"} 0
fortigate_central_management_registration_status{mode="",status="registered",vdom="root"} 1
fortigate_central_management_registration_status{mode="",status="unknown",vdom="test1"} 1
fortigate_central_management_registration_status{mode="",status="unknown",vdom="root"} 0
fortigate_central_management_registration_status{mode="",status="unregistered",vdom="test1"} 0
fortigate_central_management_registration_status{mode="",status="unregistered",vdom="root"} 0
`

if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil {
t.Fatalf("metric compare: err %v", err)
}
}
5 changes: 5 additions & 0 deletions pkg/probe/system_fortimanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ type SystemFortimanagerStatus struct {
}

func probeSystemFortimanagerStatus(c http.FortiHTTP, meta *TargetMetadata) ([]prometheus.Metric, bool) {
// Deprecated API call in FortiOS v7.6.0
if meta.VersionMajor > 7 || (meta.VersionMajor == 7 && meta.VersionMinor >= 6) {
log.Printf("Deprecated probe in FortiOS 7.6+ System/Fortimanager/Status - replaced by System/CentralManagement/Status")
return []prometheus.Metric{}, false
}
var (
FortimanStat_id = prometheus.NewDesc(
"fortigate_fortimanager_connection_status",
Expand Down
39 changes: 39 additions & 0 deletions pkg/probe/testdata/system-central-management-status.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# api/v2/monitor/system/central-management/status?vdom=*
[
{
"http_method":"GET",
"results":{
"status":"up",
"registration_status":"registered",
"sn":"F2K60FTK00000000",
"mgmt_ip":"::ffff:172.25.150.122",
"mgmt_port":443
},
"vdom":"root",
"path":"system",
"name":"central-management",
"action":"status",
"status":"success",
"serial":"F2K60FTK00000000",
"version":"v7.4.5",
"build":2702
},
{
"http_method":"GET",
"results":{
"status":"handshake",
"registration_status":"unknown",
"sn":"F2K60FTK00000000",
"mgmt_ip":"::ffff:172.25.150.122",
"mgmt_port":443
},
"vdom":"test1",
"path":"system",
"name":"central-management",
"action":"status",
"status":"success",
"serial":"F2K60FTK00000000",
"version":"v7.4.5",
"build":2702
}
]

0 comments on commit 96ec047

Please sign in to comment.