Skip to content

Commit d83f615

Browse files
authored
Merge pull request #2 from Philldomd/feature/sandbox-information
Feature/sandbox information
2 parents 857bd72 + a303cbf commit d83f615

12 files changed

Lines changed: 449 additions & 0 deletions

README.md

100644100755
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ To improve security, limit permissions to required ones only (least privilege pr
192192
|System/Resource/Usage/VDOM | sysgrp.cfg |api/v2/monitor/system/resource/usage |
193193
|System/SensorInfo | sysgrp.cfg |api/v2/monitor/system/sensor-info |
194194
|System/Status | *any* |api/v2/monitor/system/status |
195+
|System/Sandbox/Connection | sysgrp.cfg |api/v2/monitor/system/sandbox/connection|
196+
|System/Sandbox/Status | sysgrp.cfg |api/v2/monitor/system/sandbox/status|
197+
|System/Sandbox/Stats | sysgrp.cfg |api/v2/monitor/system/sandbox/stats|
195198
|System/Time/Clock | sysgrp.cfg |api/v2/monitor/system/time |
196199
|System/System/VDOMResource | sysgrp.cfg |api/v2/monitor/system/vdom-resource |
197200
|User/Fsso | authgrp |api/v2/monitor/user/fsso |

metrics.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ Global:
5151
* _WebUI/State_
5252
* `fortigate_last_reboot_seconds`
5353
* `fortigate_last_snapshot_seconds`
54+
* _System/Sandbox_
55+
* `fortigate_sandbox_status_signature_count`
56+
* `fortigate_sandbox_connection_status`
57+
* `fortigate_sandbox_stats_clean_total`
58+
* `fortigate_sandbox_stats_detected_total`
59+
* `fortigate_sandbox_stats_risk_high_total`
60+
* `fortigate_sandbox_stats_risk_medium_total`
61+
* `fortigate_sandbox_stats_risk_low_total`
62+
* `fortigate_sandbox_stats_submitted_total`
5463

5564
Per-VDOM:
5665

pkg/probe/probe.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ func (p *Collector) Probe(ctx context.Context, target map[string]string, hc *htt
160160
{"System/Status", probeSystemStatus},
161161
{"System/VDOMResource", probeSystemVdomResource},
162162
{"System/HAChecksum", probeSystemHAChecksum},
163+
{"System/Sandbox/Connection", probeSystemSandboxConnection},
164+
{"System/Sandbox/Status", probeSystemSandboxStatus},
165+
{"System/Sandbox/Stats", probeSystemSandboxStats},
163166
{"User/Fsso", probeUserFsso},
164167
{"VPN/IPSec", probeVPNIPSec},
165168
{"VPN/Ssl/Connections", probeVPNSsl},
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package probe
15+
16+
import (
17+
"log"
18+
19+
"github.com/prometheus/client_golang/prometheus"
20+
21+
"github.com/prometheus-community/fortigate_exporter/pkg/http"
22+
)
23+
24+
func probeSystemSandboxConnection(c http.FortiHTTP, _ *TargetMetadata) ([]prometheus.Metric, bool) {
25+
connectionStatusDisable := prometheus.NewDesc(
26+
"fortigate_sandbox_connection_status_disabled",
27+
"Sandbox connection status",
28+
[]string{"sandbox_type"}, nil,
29+
)
30+
connectionStatusUreachable := prometheus.NewDesc(
31+
"fortigate_sandbox_connection_status_unreachable",
32+
"Sandbox connection status",
33+
[]string{"sandbox_type"}, nil,
34+
)
35+
connectionStatusReachable := prometheus.NewDesc(
36+
"fortigate_sandbox_connection_status_reachable",
37+
"Sandbox connection status",
38+
[]string{"sandbox_type"}, nil,
39+
)
40+
41+
type SystemSandboxConnection struct {
42+
Status string `json:"status"`
43+
Type string `json:"type"`
44+
}
45+
46+
type SystemSandboxConnectionResult struct {
47+
Results []SystemSandboxConnection `json:"results"`
48+
}
49+
var res SystemSandboxConnectionResult
50+
if err := c.Get("api/v2/monitor/system/sandbox/connection", "", &res); err != nil {
51+
log.Printf("Warning: %v", err)
52+
return nil, false
53+
}
54+
55+
m := []prometheus.Metric{}
56+
for _, r := range res.Results {
57+
switch r.Status {
58+
case "unreachable":
59+
m = append(m, prometheus.MustNewConstMetric(connectionStatusUreachable, prometheus.GaugeValue, 1, r.Type))
60+
m = append(m, prometheus.MustNewConstMetric(connectionStatusReachable, prometheus.GaugeValue, 0, r.Type))
61+
m = append(m, prometheus.MustNewConstMetric(connectionStatusDisable, prometheus.GaugeValue, 0, r.Type))
62+
case "reachable":
63+
m = append(m, prometheus.MustNewConstMetric(connectionStatusUreachable, prometheus.GaugeValue, 0, r.Type))
64+
m = append(m, prometheus.MustNewConstMetric(connectionStatusReachable, prometheus.GaugeValue, 1, r.Type))
65+
m = append(m, prometheus.MustNewConstMetric(connectionStatusDisable, prometheus.GaugeValue, 0, r.Type))
66+
case "disabled":
67+
m = append(m, prometheus.MustNewConstMetric(connectionStatusUreachable, prometheus.GaugeValue, 0, r.Type))
68+
m = append(m, prometheus.MustNewConstMetric(connectionStatusReachable, prometheus.GaugeValue, 0, r.Type))
69+
m = append(m, prometheus.MustNewConstMetric(connectionStatusDisable, prometheus.GaugeValue, 1, r.Type))
70+
}
71+
}
72+
return m, true
73+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package probe
15+
16+
import (
17+
"strings"
18+
"testing"
19+
20+
"github.com/prometheus/client_golang/prometheus"
21+
"github.com/prometheus/client_golang/prometheus/testutil"
22+
)
23+
24+
func TestSystemSandboxConnection(t *testing.T) {
25+
c := newFakeClient()
26+
c.prepare("api/v2/monitor/system/sandbox/connection", "testdata/system-sandbox-connection.jsonnet")
27+
r := prometheus.NewPedanticRegistry()
28+
if !testProbe(probeSystemSandboxConnection, c, r) {
29+
t.Errorf("probeSystemSandboxConnection() returned non-success")
30+
}
31+
32+
em := `
33+
# HELP fortigate_sandbox_connection_status_disabled Sandbox connection status
34+
# TYPE fortigate_sandbox_connection_status_disabled gauge
35+
fortigate_sandbox_connection_status_disabled{sandbox_type="appliance"} 0
36+
# HELP fortigate_sandbox_connection_status_reachable Sandbox connection status
37+
# TYPE fortigate_sandbox_connection_status_reachable gauge
38+
fortigate_sandbox_connection_status_reachable{sandbox_type="appliance"} 1
39+
# HELP fortigate_sandbox_connection_status_unreachable Sandbox connection status
40+
# TYPE fortigate_sandbox_connection_status_unreachable gauge
41+
fortigate_sandbox_connection_status_unreachable{sandbox_type="appliance"} 0
42+
`
43+
44+
if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil {
45+
t.Fatalf("metric compare: err %v", err)
46+
}
47+
}

pkg/probe/system_sandbox_stats.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2025 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package probe
15+
16+
import (
17+
"log"
18+
19+
"github.com/prometheus/client_golang/prometheus"
20+
21+
"github.com/prometheus-community/fortigate_exporter/pkg/http"
22+
)
23+
24+
func probeSystemSandboxStats(c http.FortiHTTP, _ *TargetMetadata) ([]prometheus.Metric, bool) {
25+
var (
26+
numberDetected = prometheus.NewDesc(
27+
"fortigate_sandbox_stats_detected_total",
28+
"Number of detected files",
29+
[]string{}, nil,
30+
)
31+
numberClean = prometheus.NewDesc(
32+
"fortigate_sandbox_stats_clean_total",
33+
"Number of clean files",
34+
[]string{}, nil,
35+
)
36+
numberRiskLow = prometheus.NewDesc(
37+
"fortigate_sandbox_stats_risk_low_total",
38+
"Number of low risk files detected",
39+
[]string{}, nil,
40+
)
41+
numberRiskMedium = prometheus.NewDesc(
42+
"fortigate_sandbox_stats_risk_medium_total",
43+
"Number of medium risk files detected",
44+
[]string{}, nil,
45+
)
46+
numberRiskHigh = prometheus.NewDesc(
47+
"fortigate_sandbox_stats_risk_high_total",
48+
"Number of high risk files detected",
49+
[]string{}, nil,
50+
)
51+
numberSubmitted = prometheus.NewDesc(
52+
"fortigate_sandbox_stats_submitted_total",
53+
"Number of submitted files",
54+
[]string{}, nil,
55+
)
56+
)
57+
58+
type SystemSandboxStats struct {
59+
Detected float64
60+
Clean float64
61+
Low float64 `json:"risk_low"`
62+
Medium float64 `json:"risk_med"`
63+
High float64 `json:"risk_high"`
64+
Submitted float64
65+
}
66+
67+
type SystemSandboxStatsResult struct {
68+
Results []SystemSandboxStats `json:"results"`
69+
}
70+
71+
var res SystemSandboxStatsResult
72+
if err := c.Get("api/v2/monitor/system/sandbox/stats", "", &res); err != nil {
73+
log.Printf("Warning: %v", err)
74+
return nil, false
75+
}
76+
m := []prometheus.Metric{}
77+
78+
for _, r := range res.Results {
79+
m = append(m, prometheus.MustNewConstMetric(numberDetected, prometheus.CounterValue, r.Detected))
80+
m = append(m, prometheus.MustNewConstMetric(numberClean, prometheus.CounterValue, r.Clean))
81+
m = append(m, prometheus.MustNewConstMetric(numberRiskLow, prometheus.CounterValue, r.Low))
82+
m = append(m, prometheus.MustNewConstMetric(numberRiskMedium, prometheus.CounterValue, r.Medium))
83+
m = append(m, prometheus.MustNewConstMetric(numberRiskHigh, prometheus.CounterValue, r.High))
84+
m = append(m, prometheus.MustNewConstMetric(numberSubmitted, prometheus.CounterValue, r.Submitted))
85+
}
86+
return m, true
87+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2025 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package probe
15+
16+
import (
17+
"strings"
18+
"testing"
19+
20+
"github.com/prometheus/client_golang/prometheus"
21+
"github.com/prometheus/client_golang/prometheus/testutil"
22+
)
23+
24+
func TestSystemSandboxStats(t *testing.T) {
25+
c := newFakeClient()
26+
c.prepare("api/v2/monitor/system/sandbox/stats", "testdata/system-sandbox-stats.jsonnet")
27+
r := prometheus.NewPedanticRegistry()
28+
if !testProbe(probeSystemSandboxStats, c, r) {
29+
t.Errorf("probeSystemSandboxStats() returned non-success")
30+
}
31+
32+
em := `
33+
# HELP fortigate_sandbox_stats_clean_total Number of clean files
34+
# TYPE fortigate_sandbox_stats_clean_total counter
35+
fortigate_sandbox_stats_clean_total 45120
36+
# HELP fortigate_sandbox_stats_detected_total Number of detected files
37+
# TYPE fortigate_sandbox_stats_detected_total counter
38+
fortigate_sandbox_stats_detected_total 10
39+
# HELP fortigate_sandbox_stats_risk_high_total Number of high risk files detected
40+
# TYPE fortigate_sandbox_stats_risk_high_total counter
41+
fortigate_sandbox_stats_risk_high_total 5
42+
# HELP fortigate_sandbox_stats_risk_low_total Number of low risk files detected
43+
# TYPE fortigate_sandbox_stats_risk_low_total counter
44+
fortigate_sandbox_stats_risk_low_total 3
45+
# HELP fortigate_sandbox_stats_risk_medium_total Number of medium risk files detected
46+
# TYPE fortigate_sandbox_stats_risk_medium_total counter
47+
fortigate_sandbox_stats_risk_medium_total 2
48+
# HELP fortigate_sandbox_stats_submitted_total Number of submitted files
49+
# TYPE fortigate_sandbox_stats_submitted_total counter
50+
fortigate_sandbox_stats_submitted_total 45130
51+
`
52+
53+
if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil {
54+
t.Fatalf("metric compare: err %v", err)
55+
}
56+
}

pkg/probe/system_sandbox_status.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package probe
15+
16+
import (
17+
"log"
18+
"strconv"
19+
20+
"github.com/prometheus/client_golang/prometheus"
21+
22+
"github.com/prometheus-community/fortigate_exporter/pkg/http"
23+
)
24+
25+
func probeSystemSandboxStatus(c http.FortiHTTP, _ *TargetMetadata) ([]prometheus.Metric, bool) {
26+
Count := prometheus.NewDesc(
27+
"fortigate_system_sandbox_status_signatures_count",
28+
"The number of signatures that have been loaded on the FortiSandbox.",
29+
[]string{"configured", "type", "cloud_region", "server", "malware_package_version", "signatures_loaded", "vdom"}, nil,
30+
)
31+
32+
type SystemSandboxStatus struct {
33+
Configured bool `json:"configured"`
34+
Type string `json:"type"`
35+
Cloud string `json:"cloud_region"`
36+
Server string `json:"server"`
37+
MPV string `json:"malware_package_version"`
38+
Loaded bool `json:"signatures_loaded"`
39+
Count float64 `json:"signatures_count"`
40+
}
41+
42+
type SystemSandboxStatusResult struct {
43+
Result SystemSandboxStatus `json:"results"`
44+
VDOM string `json:"vdom"`
45+
}
46+
47+
var res SystemSandboxStatusResult
48+
if err := c.Get("api/v2/monitor/system/sandbox/status", "", &res); err != nil {
49+
log.Printf("Warning: %v", err)
50+
return nil, false
51+
}
52+
m := []prometheus.Metric{}
53+
cloud := "null"
54+
if res.Result.Cloud != "" {
55+
cloud = res.Result.Cloud
56+
}
57+
m = append(m, prometheus.MustNewConstMetric(
58+
Count,
59+
prometheus.GaugeValue,
60+
res.Result.Count,
61+
strconv.FormatBool(res.Result.Configured),
62+
res.Result.Type,
63+
cloud,
64+
res.Result.Server,
65+
res.Result.MPV,
66+
strconv.FormatBool(res.Result.Loaded),
67+
res.VDOM),
68+
)
69+
return m, true
70+
}

0 commit comments

Comments
 (0)