Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added CentralManagement Status metrics, replaces Fortimanager Status #305

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
]
Loading