diff --git a/src/network/stormshield/api/mode/listvpntunnels.pm b/src/network/stormshield/api/mode/listvpntunnels.pm
new file mode 100644
index 000000000..721d9ea50
--- /dev/null
+++ b/src/network/stormshield/api/mode/listvpntunnels.pm
@@ -0,0 +1,111 @@
+#
+# Copyright 2025 Centreon (http://www.centreon.com/)
+#
+# Centreon is a full-fledged industry-strength solution that meets
+# the needs in IT infrastructure and application monitoring for
+# service performance.
+#
+# 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 network::stormshield::api::mode::listvpntunnels;
+
+use base qw(centreon::plugins::mode);
+
+use strict;
+use warnings;
+
+my @labels = (
+ 'ikeStatus',
+ 'name'
+);
+
+sub new {
+ my ($class, %options) = @_;
+ my $self = $class->SUPER::new(package => __PACKAGE__, %options);
+ bless $self, $class;
+
+ $options{options}->add_options(arguments => {});
+
+ return $self;
+}
+
+sub check_options {
+ my ($self, %options) = @_;
+ $self->SUPER::init(%options);
+}
+
+sub manage_selection {
+ my ($self, %options) = @_;
+
+ my $result = $options{custom}->request(command => 'monitor getikesa');
+
+ my $results = {};
+ foreach my $entry (@{$result->{Result}}) {
+ $results->{ $entry->{id} } = {
+ name => $entry->{rulename},
+ ikeStatus => $entry->{state}
+ };
+ }
+
+ return $results;
+}
+
+sub run {
+ my ($self, %options) = @_;
+
+ my $results = $self->manage_selection(custom => $options{custom});
+ foreach my $instance (sort keys %$results) {
+ $self->{output}->output_add(long_msg =>
+ join('', map("[$_: " . $results->{$instance}->{$_} . ']', @labels))
+ );
+ }
+
+ $self->{output}->output_add(
+ severity => 'OK',
+ short_msg => 'List VPN tunnels:'
+ );
+ $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
+ $self->{output}->exit();
+}
+
+sub disco_format {
+ my ($self, %options) = @_;
+
+ $self->{output}->add_disco_format(elements => [@labels]);
+}
+
+sub disco_show {
+ my ($self, %options) = @_;
+
+ my $results = $self->manage_selection(custom => $options{custom});
+ foreach (sort keys %$results) {
+ $self->{output}->add_disco_entry(
+ %{$results->{$_}}
+ );
+ }
+}
+
+1;
+
+__END__
+
+=head1 MODE
+
+List VPN tunnels.
+
+=over 8
+
+=back
+
+=cut
\ No newline at end of file
diff --git a/src/network/stormshield/api/mode/vpntunnels.pm b/src/network/stormshield/api/mode/vpntunnels.pm
new file mode 100644
index 000000000..5920df353
--- /dev/null
+++ b/src/network/stormshield/api/mode/vpntunnels.pm
@@ -0,0 +1,273 @@
+#
+# Copyright 2025 Centreon (http://www.centreon.com/)
+#
+# Centreon is a full-fledged industry-strength solution that meets
+# the needs in IT infrastructure and application monitoring for
+# service performance.
+#
+# 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 network::stormshield::api::mode::vpntunnels;
+
+use base qw(centreon::plugins::templates::counter);
+
+use strict;
+use warnings;
+use Digest::MD5 qw(md5_hex);
+use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
+
+sub custom_status_output {
+ my ($self, %options) = @_;
+
+ return 'ike status: ' . $self->{result_values}->{ikeStatus};
+}
+
+sub custom_packets_output {
+ my ($self, %options) = @_;
+
+ return sprintf(
+ 'packets %s: %s',
+ $self->{result_values}->{label},
+ $self->{result_values}->{value_absolute}
+ );
+}
+
+sub custom_traffic_output {
+ my ($self, %options) = @_;
+
+ my ($traffic_value, $traffic_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{value_per_second}, network => 1);
+ return sprintf(
+ 'traffic %s: %s/s',
+ $self->{result_values}->{label},
+ $traffic_value . $traffic_unit
+ );
+}
+
+sub custom_metric_calc {
+ my ($self, %options) = @_;
+
+ my ($checked, $total) = (0, 0);
+ foreach (keys %{$options{new_datas}}) {
+ if (/$self->{instance}_$options{extra_options}->{instance_ref}_(.+)/) {
+ $checked |= 1;
+ my $new = $options{new_datas}->{$_};
+ next if (!defined($options{old_datas}->{$_}));
+ my $old = $options{old_datas}->{$_};
+
+ $checked |= 2;
+ my $diff = $new - $old;
+ if ($diff < 0) {
+ $total += $new;
+ } else {
+ $total += $diff;
+ }
+ }
+ }
+
+ if ($checked == 0) {
+ $self->{error_msg} = 'skipped (no value)';
+ return -10;
+ }
+ if ($checked == 1) {
+ $self->{error_msg} = 'buffer creation';
+ return -1;
+ }
+
+ $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'};
+ $self->{result_values}->{value_per_second} = $total / $options{delta_time};
+ $self->{result_values}->{value_absolute} = $total;
+ $self->{result_values}->{label} = $options{extra_options}->{label_ref};
+ return 0;
+}
+
+sub prefix_tunnel_output {
+ my ($self, %options) = @_;
+
+ return "VPN tunnel '" . $options{instance_value}->{name} . "' ";
+}
+
+sub set_counters {
+ my ($self, %options) = @_;
+
+ $self->{maps_counters_type} = [
+ { name => 'global', type => 0 },
+ { name => 'tunnels', type => 1, cb_prefix_output => 'prefix_tunnel_output', message_multiple => 'All VPN tunnels are ok', skipped_code => { -10 => 1 } }
+ ];
+
+ $self->{maps_counters}->{global} = [
+ { label => 'tunnels-total', nlabel => 'vpn.tunnels.total.count', set => {
+ key_values => [ { name => 'total' } ],
+ output_template => 'Total VPN tunnels: %s',
+ perfdatas => [
+ { template => '%s', min => 0 }
+ ]
+ }
+ }
+ ];
+
+ $self->{maps_counters}->{tunnels} = [
+ {
+ label => 'status',
+ type => 2,
+ warning_default => '%{ikeStatus} =~ /connecting/',
+ set => {
+ key_values => [ { name => 'ikeStatus' }, { name => 'name' } ],
+ closure_custom_output => $self->can('custom_status_output'),
+ closure_custom_perfdata => sub { return 0; },
+ closure_custom_threshold_check => \&catalog_status_threshold_ng
+ }
+ },
+ { label => 'tunnel-traffic-in', nlabel => 'vpn.tunnel.traffic.in.bitspersecond', set => {
+ key_values => [],
+ manual_keys => 1,
+ closure_custom_calc => $self->can('custom_metric_calc'),
+ closure_custom_calc_extra_options => { instance_ref => 'traffic_in', label_ref => 'in' },
+ closure_custom_output => $self->can('custom_traffic_output'),
+ threshold_use => 'value_per_second',
+ perfdatas => [
+ { template => '%s', value => 'value_per_second', min => 0, unit => 'b/s', label_extra_instance => 1 }
+ ]
+ }
+ },
+ { label => 'tunnel-traffic-out', nlabel => 'vpn.tunnel.traffic.out.bitspersecond', set => {
+ key_values => [],
+ manual_keys => 1,
+ closure_custom_calc => $self->can('custom_metric_calc'),
+ closure_custom_calc_extra_options => { instance_ref => 'traffic_out', label_ref => 'traffic_out' },
+ closure_custom_output => $self->can('custom_traffic_output'),
+ threshold_use => 'value_per_second',
+ perfdatas => [
+ { template => '%s', value => 'value_per_second', min => 0, unit => 'b/s', label_extra_instance => 1 }
+ ]
+ }
+ },
+ { label => 'tunnel-packets-in', nlabel => 'vpn.tunnel.packets.in.count', set => {
+ key_values => [],
+ manual_keys => 1,
+ closure_custom_calc => $self->can('custom_metric_calc'),
+ closure_custom_calc_extra_options => { instance_ref => 'packets_in', label_ref => 'in' },
+ closure_custom_output => $self->can('custom_packets_output'),
+ threshold_use => 'value_absolute',
+ perfdatas => [
+ { template => '%s', value => 'value_absolute', min => 0, label_extra_instance => 1 }
+ ]
+ }
+ },
+ { label => 'tunnel-packets-out', nlabel => 'vpn.tunnel.packets.out.count', set => {
+ key_values => [],
+ manual_keys => 1,
+ closure_custom_calc => $self->can('custom_metric_calc'),
+ closure_custom_calc_extra_options => { instance_ref => 'packets_out', label_ref => 'out' },
+ closure_custom_output => $self->can('custom_packets_output'),
+ threshold_use => 'value_absolute',
+ perfdatas => [
+ { template => '%s', value => 'value_absolute', min => 0, label_extra_instance => 1 }
+ ]
+ }
+ }
+ ];
+}
+
+sub new {
+ my ($class, %options) = @_;
+ my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1);
+ bless $self, $class;
+
+ $options{options}->add_options(arguments => {
+ 'filter-name:s' => { name => 'filter_name' }
+ });
+
+ return $self;
+}
+
+sub manage_selection {
+ my ($self, %options) = @_;
+
+ my $result = $options{custom}->request(command => 'monitor getikesa');
+
+ foreach my $entry (@{$result->{Result}}) {
+ next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
+ $entry->{rulename} !~ /$self->{option_results}->{filter_name}/);
+
+ $self->{tunnels}->{ $entry->{rulename} } = {
+ name => $entry->{rulename},
+ ikeStatus => $entry->{state}
+ };
+ }
+
+ $result = $options{custom}->request(command => 'monitor getsa');
+
+ foreach my $entry (@{$result->{Result}}) {
+ next if (!defined($self->{tunnels}->{ $entry->{ikerulename} }));
+
+ my $instance = $entry->{rulename};
+
+ $self->{tunnels}->{ $entry->{ikerulename} }->{'traffic_in_' . $instance} = $entry->{bytesin} * 8;
+ $self->{tunnels}->{ $entry->{ikerulename} }->{'traffic_out_' . $instance} = $entry->{bytesout} * 8;
+ $self->{tunnels}->{ $entry->{ikerulename} }->{'packets_in_' . $instance} = $entry->{packetsin};
+ $self->{tunnels}->{ $entry->{ikerulename} }->{'packets_out_' . $instance} = $entry->{packetsout};
+ }
+
+ $self->{cache_name} = 'stormshield_' . $options{custom}->get_connection_info() . '_' . $self->{mode} . '_' .
+ md5_hex(
+ (defined($self->{option_results}->{filter_counters}) ? $self->{option_results}->{filter_counters} : '') . '_' .
+ (defined($self->{option_results}->{filter_name}) ? $self->{option_results}->{filter_name} : '')
+ );
+
+ $self->{global} = { total => scalar(keys %{$self->{tunnels}}) };
+}
+
+1;
+
+__END__
+
+=head1 MODE
+
+Check VPN tunnels.
+
+=over 8
+
+=item B<--filter-name>
+
+Filter name (can be a regexp).
+
+=item B<--filter-counters>
+
+Only display some counters (regexp can be used).
+Example: --filter-counters='tunnels-total'
+
+=item B<--unknown-status>
+
+Define the conditions to match for the status to be UNKNOWN.
+You can use the following variables: %{ikeStatus}, %{name}
+
+=item B<--warning-status>
+
+Define the conditions to match for the status to be WARNING (default: '%{ikeStatus} =~ /connecting/'.
+You can use the following variables: %{ikeStatus}, %{name}
+
+=item B<--critical-status>
+
+Define the conditions to match for the status to be CRITICAL.
+You can use the following variables: %{ikeStatus}, %{name}
+
+=item B<--warning-*> B<--critical-*>
+
+Thresholds.
+Can be: 'tunnels-total', 'tunnel-traffic-in', 'tunnel-traffic-out',
+'tunnel-packets-in', 'tunnel-packets-out'.
+
+=back
+
+=cut
diff --git a/src/network/stormshield/api/plugin.pm b/src/network/stormshield/api/plugin.pm
index 1ac9313ab..c075ac3d2 100644
--- a/src/network/stormshield/api/plugin.pm
+++ b/src/network/stormshield/api/plugin.pm
@@ -30,14 +30,16 @@ sub new {
bless $self, $class;
$self->{modes} = {
- 'cpu' => 'network::stormshield::api::mode::cpu',
- 'ha' => 'network::stormshield::api::mode::ha',
- 'hardware' => 'network::stormshield::api::mode::hardware',
- 'health' => 'network::stormshield::api::mode::health',
- 'interfaces' => 'network::stormshield::api::mode::interfaces',
- 'list-interfaces' => 'network::stormshield::api::mode::listinterfaces',
- 'memory' => 'network::stormshield::api::mode::memory',
- 'uptime' => 'network::stormshield::api::mode::uptime'
+ 'cpu' => 'network::stormshield::api::mode::cpu',
+ 'ha' => 'network::stormshield::api::mode::ha',
+ 'hardware' => 'network::stormshield::api::mode::hardware',
+ 'health' => 'network::stormshield::api::mode::health',
+ 'interfaces' => 'network::stormshield::api::mode::interfaces',
+ 'list-interfaces' => 'network::stormshield::api::mode::listinterfaces',
+ 'list-vpn-tunnels' => 'network::stormshield::api::mode::listvpntunnels',
+ 'memory' => 'network::stormshield::api::mode::memory',
+ 'uptime' => 'network::stormshield::api::mode::uptime',
+ 'vpn-tunnels' => 'network::stormshield::api::mode::vpntunnels'
};
$self->{custom_modes}->{api} = 'network::stormshield::api::custom::api';
diff --git a/tests/network/stormshield/api/Mockoon.json b/tests/network/stormshield/api/Mockoon.json
new file mode 100644
index 000000000..56f9c8fb0
--- /dev/null
+++ b/tests/network/stormshield/api/Mockoon.json
@@ -0,0 +1,169 @@
+{
+ "uuid": "c0a1a49e-58d9-49e8-bd8e-9eca9b7fe197",
+ "lastMigration": 32,
+ "name": "New environment",
+ "endpointPrefix": "",
+ "latency": 0,
+ "port": 3000,
+ "hostname": "",
+ "rootChildren": [
+ {
+ "type": "route",
+ "uuid": "8cd81000-5c93-4799-97a3-e61978797b22"
+ },
+ {
+ "type": "route",
+ "uuid": "cfd8d8b8-2473-405c-a6b8-4e15dbd89b3e"
+ },
+ {
+ "type": "route",
+ "uuid": "b6f05284-391c-4a75-9525-03162ebb5856"
+ }
+ ],
+ "folders": [],
+ "routes": [
+ {
+ "uuid": "8cd81000-5c93-4799-97a3-e61978797b22",
+ "type": "http",
+ "documentation": "",
+ "method": "post",
+ "endpoint": "auth/admin.html",
+ "responses": [
+ {
+ "uuid": "02882e1f-30f7-4edc-aa92-88b12897fa92",
+ "body": "",
+ "latency": 0,
+ "statusCode": 200,
+ "label": "",
+ "headers": [
+ {
+ "key": "Set-Cookie",
+ "value": "NETASQ_sslclient=abcdefg123; Path=/api/; Secure; HttpOnly; SameSite=Strict"
+ }
+ ],
+ "bodyType": "INLINE",
+ "filePath": "",
+ "databucketID": "",
+ "sendFileAsBody": false,
+ "rules": [
+ {
+ "target": "body",
+ "modifier": "",
+ "value": "app=sslclient&pswd=azerty123&uid=qwerty123",
+ "invert": false,
+ "operator": "equals"
+ }
+ ],
+ "rulesOperator": "OR",
+ "disableTemplating": false,
+ "fallbackTo404": false,
+ "default": true,
+ "crudKey": "id",
+ "callbacks": []
+ }
+ ],
+ "responseMode": null
+ },
+ {
+ "uuid": "cfd8d8b8-2473-405c-a6b8-4e15dbd89b3e",
+ "type": "http",
+ "documentation": "",
+ "method": "post",
+ "endpoint": "api/auth/login",
+ "responses": [
+ {
+ "uuid": "c7548a37-47c4-4df0-9ecc-9ba3613eb05d",
+ "body": "\r\nAZEQERSFSRSTSTSTSTSTSTTadminSFAZERTY15HH18SF25754A7514modify,mon_write,base,contentfilter,log,filter,vpn,log_read,pki,object,user,admin,network,route,maintenance,asq,pvm,vpn_read,filter_read,report,report_read,globalobject,globalfilter,guest_admin,privacy,privacy_read,tpm,consolebase,contentfilter,log,filter,vpn,log_read,pki,object,user,admin,network,route,maintenance,asq,pvm,vpn_read,filter_read,report,report_read,globalobject,globalfilter,guest_admin,privacy,privacy_read,tpm,consoledirect127.0.0.1vlan600",
+ "latency": 0,
+ "statusCode": 200,
+ "label": "",
+ "headers": [
+ {
+ "key": "Accept",
+ "value": "*/*"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/x-www-form-urlencoded"
+ },
+ {
+ "key": "Set-Cookie",
+ "value": "azerty123"
+ },
+ {
+ "key": "X-Content-Type-Options",
+ "value": "nosniff"
+ },
+ {
+ "key": "X-Frame-Options",
+ "value": "deny"
+ },
+ {
+ "key": "Content-Security-Policy",
+ "value": "frame-ancestors"
+ }
+ ],
+ "bodyType": "INLINE",
+ "filePath": "",
+ "databucketID": "",
+ "sendFileAsBody": false,
+ "rules": [],
+ "rulesOperator": "OR",
+ "disableTemplating": false,
+ "fallbackTo404": false,
+ "default": true,
+ "crudKey": "id",
+ "callbacks": []
+ }
+ ],
+ "responseMode": null
+ },
+ {
+ "uuid": "b6f05284-391c-4a75-9525-03162ebb5856",
+ "type": "http",
+ "documentation": "",
+ "method": "get",
+ "endpoint": "api/command",
+ "responses": [
+ {
+ "uuid": "4cc9b593-ea33-4c15-bb5e-c388c17885e8",
+ "body": "\r\n",
+ "latency": 0,
+ "statusCode": 200,
+ "label": "",
+ "headers": [],
+ "bodyType": "INLINE",
+ "filePath": "",
+ "databucketID": "",
+ "sendFileAsBody": false,
+ "rules": [],
+ "rulesOperator": "OR",
+ "disableTemplating": false,
+ "fallbackTo404": false,
+ "default": true,
+ "crudKey": "id",
+ "callbacks": []
+ }
+ ],
+ "responseMode": null
+ }
+ ],
+ "proxyMode": false,
+ "proxyHost": "",
+ "proxyRemovePrefix": false,
+ "tlsOptions": {
+ "enabled": false,
+ "type": "CERT",
+ "pfxPath": "",
+ "certPath": "",
+ "keyPath": "",
+ "caPath": "",
+ "passphrase": ""
+ },
+ "cors": true,
+ "headers": [],
+ "proxyReqHeaders": [],
+ "proxyResHeaders": [],
+ "data": [],
+ "callbacks": []
+}
\ No newline at end of file
diff --git a/tests/network/stormshield/api/list_vpn_tunnels.robot b/tests/network/stormshield/api/list_vpn_tunnels.robot
new file mode 100644
index 000000000..59c856e55
--- /dev/null
+++ b/tests/network/stormshield/api/list_vpn_tunnels.robot
@@ -0,0 +1,40 @@
+*** Settings ***
+
+Resource ${CURDIR}${/}..${/}..${/}..${/}resources/import.resource
+
+Suite Setup Start Mockoon ${MOCKOON_JSON}
+Suite Teardown Stop Mockoon
+Test Timeout 120s
+
+
+*** Variables ***
+${MOCKOON_JSON} ${CURDIR}${/}Mockoon.json
+
+${cmd} ${CENTREON_PLUGINS}
+... --plugin=network::stormshield::api::plugin
+... --mode=list-vpn-tunnels
+... --custommode=api
+... --hostname=${HOSTNAME}
+... --api-username=username
+... --api-password=password
+... --proto=http
+... --port=${APIPORT}
+... --timeout=5
+
+
+*** Test Cases ***
+list-vpn-tunnels ${tc}
+ [Tags] network api
+ ${output} Run ${CMD} ${extraoptions} | wc -l
+
+ ${output} Strip String ${output}
+ Should Be Equal As Strings
+ ... ${output}
+ ... ${expected_result}
+ ... Wrong output result for command:\n${CMD} ${extraoptions}\n\nObtained:\n${output}\n\nExpected:\n${expected_result}\n
+ ... values=False
+ ... collapse_spaces=True
+
+
+ Examples: tc extraoptions expected_result --
+ ... 1 ${EMPTY} 24
diff --git a/tests/network/stormshield/api/vpn-tunnels.robot b/tests/network/stormshield/api/vpn-tunnels.robot
new file mode 100644
index 000000000..c00df3405
--- /dev/null
+++ b/tests/network/stormshield/api/vpn-tunnels.robot
@@ -0,0 +1,41 @@
+*** Settings ***
+
+Resource ${CURDIR}${/}..${/}..${/}..${/}resources/import.resource
+
+Suite Setup Start Mockoon ${MOCKOON_JSON}
+Suite Teardown Stop Mockoon
+Test Timeout 120s
+
+
+*** Variables ***
+${MOCKOON_JSON} ${CURDIR}${/}Mockoon.json
+
+${cmd} ${CENTREON_PLUGINS}
+... --plugin=network::stormshield::api::plugin
+... --custommode=api
+... --hostname=${HOSTNAME}
+... --api-username=username
+... --api-password=password
+... --proto=http
+... --port=${APIPORT}
+... --timeout=5
+
+
+*** Test Cases ***
+vpn-tunnels ${tc}
+ [Tags] network api
+ ${command} Catenate
+ ... ${cmd}
+ ... --mode=vpn-tunnels
+ ... ${extraoptions}
+
+ Ctn Run Command And Check Result As Strings ${command} ${expected_result}
+
+ Examples: tc extraoptions expected_result --
+ ... 1 ${EMPTY} OK: Total VPN tunnels: 22 - All VPN tunnels are ok | 'vpn.tunnels.total.count'=22;;;0;
+ ... 2 --filter-name='7ddb9fbb1faab23401c19beb20e31b62' OK: Total VPN tunnels: 1 - VPN tunnel '7ddb9fbb1faab23401c19beb20e31b62' ike status: installed | 'vpn.tunnels.total.count'=1;;;0;
+ ... 3 --filter-counters='tunnels-total' OK: Total VPN tunnels: 22 | 'vpn.tunnels.total.count'=22;;;0;
+ ... 4 --unknown-status='\\\%{ikeStatus} =~ /installed/' --filter-name='3061933d03c01595f6a426cfb50c5e09' UNKNOWN: VPN tunnel '3061933d03c01595f6a426cfb50c5e09' ike status: installed | 'vpn.tunnels.total.count'=1;;;0;
+ ... 5 --warning-status='\\\%{ikeStatus} =~ /installed/' --filter-name='2975a3940ace7eb1a13a006a51c66991' WARNING: VPN tunnel '2975a3940ace7eb1a13a006a51c66991' ike status: installed | 'vpn.tunnels.total.count'=1;;;0;
+ ... 6 --critical-status='\\\%{ikeStatus} =~ /installed/' --filter-name='4793e3b444d2342a46df35dd0338f2cc' CRITICAL: VPN tunnel '4793e3b444d2342a46df35dd0338f2cc' ike status: installed | 'vpn.tunnels.total.count'=1;;;0;
+ ... 7 --warning-tunnels-total=20 --critical-tunnels-total=25 WARNING: Total VPN tunnels: 22 | 'vpn.tunnels.total.count'=22;0:20;0:25;0;
diff --git a/tests/resources/spellcheck/stopwords.txt b/tests/resources/spellcheck/stopwords.txt
index 03f6f9549..ccdbcb553 100644
--- a/tests/resources/spellcheck/stopwords.txt
+++ b/tests/resources/spellcheck/stopwords.txt
@@ -247,6 +247,7 @@ SSH
standAlone
statefile
--statefile-concat-cwd
+Stormshield
SureBackup
systemd
SysVol