From 0e896346e3f83d5a1c5804e3629732fd3ce46071 Mon Sep 17 00:00:00 2001 From: Sylvain Cresto Date: Mon, 11 Aug 2025 13:38:43 +0200 Subject: [PATCH] Plugin(apps::monitoring::iplabel::ekara::restapi) - Custom(api) : Add a new authentication way (#5698) --- .../iplabel/ekara/restapi/custom/api.pm | 103 +++++--- .../iplabel/ekara/restapi/mode/incidents.pm | 18 +- .../iplabel/ekara/restapi/mode/scenarios.pm | 4 +- .../iplabel/ekara/restapi/incidents.robot | 41 ++- .../restapi/monitoring-iplabel-ekara.json | 233 +++++++++++++++++- .../iplabel/ekara/restapi/scenarios.robot | 36 ++- 6 files changed, 383 insertions(+), 52 deletions(-) diff --git a/src/apps/monitoring/iplabel/ekara/restapi/custom/api.pm b/src/apps/monitoring/iplabel/ekara/restapi/custom/api.pm index cba44f2d4..bbd778bdb 100644 --- a/src/apps/monitoring/iplabel/ekara/restapi/custom/api.pm +++ b/src/apps/monitoring/iplabel/ekara/restapi/custom/api.pm @@ -43,19 +43,20 @@ sub new { if (!defined($options{noptions})) { $options{options}->add_options(arguments => { - 'api-username:s' => { name => 'api_username' }, - 'api-password:s' => { name => 'api_password' }, - 'hostname:s' => { name => 'hostname' }, - 'port:s' => { name => 'port' }, - 'proto:s' => { name => 'proto' }, - 'timeout:s' => { name => 'timeout' }, - 'url-path:s' => { name => 'url_path' }, + 'api-key:s' => { name => 'api_key', default => '' }, + 'api-username:s' => { name => 'api_username', default => '' }, + 'api-password:s' => { name => 'api_password', default => '' }, + 'hostname:s' => { name => 'hostname', default => 'api.ekara.ip-label.net' }, + 'port:s' => { name => 'port', default => 443 }, + 'proto:s' => { name => 'proto', default => 'https' }, + 'timeout:s' => { name => 'timeout', default => 10 }, + 'url-path:s' => { name => 'url_path', default => '' }, 'filter-id:s' => { name => 'filter_id' }, 'filter-name:s' => { name => 'filter_name' }, 'filter-workspaceid:s' => { name => 'filter_workspaceid' }, 'filter-siteid:s' => { name => 'filter_siteid' }, 'filter-status:s@' => { name => 'filter_status' }, - 'authent-endpoint' => { name => 'authent_endpoint' } + 'authent-endpoint' => { name => 'authent_endpoint', default => '/auth/login' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); @@ -77,31 +78,40 @@ sub set_defaults {} sub check_options { my ($self, %options) = @_; + use Data::Dumper; + $self->{unknown_http_status} = $self->{option_results}->{unknown_http_status} // '%{http_code} < 200 or %{http_code} >= 300'; + $self->{warning_http_status} = $self->{option_results}->{warning_http_status} // ''; + $self->{critical_http_status} = $self->{option_results}->{critical_http_status} // ''; + + $self->{$_} = $self->{option_results}->{$_} for qw/api_key api_password api_username authent_endpoint hostname port proto timeout url_path/; - $self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : 'api.ekara.ip-label.net'; - $self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : ''; - $self->{authent_endpoint} = (defined($self->{option_results}->{authent_endpoint})) ? $self->{option_results}->{authent_endpoint} : '/auth/login'; - $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; - $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; - $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10; - $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; - $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; - $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; - $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : undef; - $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; $self->{cache}->check_options(option_results => $self->{option_results}); - if (!defined($self->{hostname}) || $self->{hostname} eq '') { + if ($self->{hostname} eq '') { $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); $self->{output}->option_exit(); } - if (!defined($self->{api_username}) || $self->{api_username} eq '') { - $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); + + # Ekara REST API support two authentication modes: API key or username/password + # Both modes cannot be used simultaneously + if (($self->{api_username} ne '' || $self->{api_password} ne '') && $self->{api_key} ne '') { + $self->{output}->add_option_msg(short_msg => "Cannot use both --api-key and --api-username/--api-password options."); $self->{output}->option_exit(); } - if (!defined($self->{api_password}) || $self->{api_password} eq '') { - $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); - $self->{output}->option_exit(); + + if ($self->{api_key} eq '') { + # username/password required if api_key is not set + foreach (qw/api_username api_password/) { + if ($self->{option_results}->{$_} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --api-key or --api-username/--api-password options."); + $self->{output}->option_exit(); + } + } + # authent_endpoint is required if username/password authentication mode is used + if ($self->{authent_endpoint} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --authent-endpoint option."); + $self->{output}->option_exit(); + } } return 0; @@ -124,7 +134,11 @@ sub settings { $self->build_options_for_httplib(); $self->{http}->add_header(key => 'Accept', value => 'application/json'); $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); - $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}) if (defined($self->{access_token})); + if ($self->{api_key} ne '') { + $self->{http}->add_header(key => 'X-API-KEY', value => $self->{api_key}); + } elsif ($self->{access_token}) { + $self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token}); + } $self->{http}->set_options(%{$self->{option_results}}); } @@ -229,7 +243,7 @@ sub request_scenarios_status{ sub request_api { my ($self, %options) = @_; - if (!defined($self->{access_token})) { + if ($self->{api_key} eq '' && !$self->{access_token}) { $self->{access_token} = $self->get_access_token(statefile => $self->{cache}); } @@ -237,7 +251,7 @@ sub request_api { my ($json, $response); - my $post_json = defined($options{post_body}) ? $options{post_body} : {}; + my $post_json = $options{post_body} // {}; $response = $self->{http}->request( get_param => $options{get_param}, @@ -247,6 +261,12 @@ sub request_api { ); $self->{output}->output_add(long_msg => $response, debug => 1); + # Bad API key returns 401 Unauthorized + if ($self->{api_key} ne '' && ($self->{http}->get_code() // '') eq '401') { + $self->{output}->add_option_msg(short_msg => "API key is not valid."); + $self->{output}->option_exit(); + } + eval { $json = JSON::XS->new->utf8->decode($response); }; @@ -271,6 +291,26 @@ ip-label Ekara Rest API ip-label Ekara Rest API +=head2 Authentication + +Ekara REST API supports two authentication modes which cannot be use simultaneously: API key or username/password. + +=over 8 + +=item B<--api-key> + +Set API key authentication. + +=item B<--api-username> + +Set username. + +=item B<--api-password> + +Set password. + +=head2 Other common API options + =over 8 =item B<--hostname> @@ -285,13 +325,6 @@ Port used (default: 443) Specify https if needed (default: 'https') -=item B<--api-username> - -Set username. - -=item B<--api-password> - -Set password. =item B<--filter-id> diff --git a/src/apps/monitoring/iplabel/ekara/restapi/mode/incidents.pm b/src/apps/monitoring/iplabel/ekara/restapi/mode/incidents.pm index 12776147e..9d23955c4 100644 --- a/src/apps/monitoring/iplabel/ekara/restapi/mode/incidents.pm +++ b/src/apps/monitoring/iplabel/ekara/restapi/mode/incidents.pm @@ -296,11 +296,21 @@ Syntax: --critical-trigger-status='%{status} =~ "xxx"' Can be 'Unknown', 'Success', 'Failure', 'Aborted', 'No execution', 'Stopped', 'Excluded', 'Degraded' -=item B<--warning-*> B<--critical-*> +=item B<--warning-incidents-total> -Thresholds. -Can be: 'warning-incidents-total' (count) 'critical-incidents-total' (count), -'warning-incident-duration' (s), 'critical-incident-duration' (s). +Threshold. + +=item B<--critical-incidents-total> + +Threshold. + +=item B<--warning-incident-duration> + +Threshold in seconds. + +=item B<--critical-incident-duration> + +Threshold in seconds. =back diff --git a/src/apps/monitoring/iplabel/ekara/restapi/mode/scenarios.pm b/src/apps/monitoring/iplabel/ekara/restapi/mode/scenarios.pm index afc4d33ea..408f18dbd 100644 --- a/src/apps/monitoring/iplabel/ekara/restapi/mode/scenarios.pm +++ b/src/apps/monitoring/iplabel/ekara/restapi/mode/scenarios.pm @@ -266,11 +266,11 @@ Syntax: --critical-scenario-status='%{status} =~ "xxx"' =item B<--warning-availability> -Thresholds in %. +Thresholds in percentage. =item B<--critical-availability> -Thresholds in %. +Thresholds in percentage. =item B<--warning-time-total-allsteps> diff --git a/tests/monitoring/iplabel/ekara/restapi/incidents.robot b/tests/monitoring/iplabel/ekara/restapi/incidents.robot index 384e5708b..e2343aefb 100644 --- a/tests/monitoring/iplabel/ekara/restapi/incidents.robot +++ b/tests/monitoring/iplabel/ekara/restapi/incidents.robot @@ -13,13 +13,44 @@ ${MOCKOON_JSON} ${CURDIR}${/}monitoring-iplabel-ekara.json ${cmd} ${CENTREON_PLUGINS} ... --plugin=apps::monitoring::iplabel::ekara::restapi::plugin ... --hostname=localhost -... --api-username='username' -... --api-password='password' ... --port='3000' ... --proto='http' *** Test Cases *** +incidents-username ${tc} + [Documentation] Check Iplabel scenarios + [Tags] monitoring iplabel restapi + + ${command} Catenate + ... ${cmd} + ... --mode=incidents + ... --api-username='username' + ... --api-password='password' + ... ${extra_options} + + Ctn Run Command And Check Result As Strings ${command} ${expected_result} + + Examples: tc extra_options expected_result -- + ... 1 --filter-name='Centreon Demo Navigation|AKILA - .Web.' CRITICAL: Incident #25421291, Scenario 'Centreon Demo Navigation' severity: Critical - Incident #25421962, Scenario 'AKILA - (Web)' severity: Critical - Incident #25422458, Scenario 'Centreon Demo Navigation' severity: Critical - Incident #25423513, Scenario 'Centreon Demo Navigation' status: Open, severity: Critical | 'ekara.incidents.current.total.count'=4;;;0; + ... 2 --filter-name='not a name' UNKNOWN: No scenarios found, can't search for incidents. Please check filters. + +incidents-apikey ${tc} + [Documentation] Check Iplabel scenarios + [Tags] monitoring iplabel restapi + + ${command} Catenate + ... ${cmd} + ... --mode=incidents + ... --api-key='PaSsWoRdZ' + ... ${extra_options} + + Ctn Run Command And Check Result As Strings ${command} ${expected_result} + + Examples: tc extra_options expected_result -- + ... 1 --filter-name='X-Centreon Demo Navigation|X-AKILA - .Web.' CRITICAL: Incident #25421291, Scenario 'X-Centreon Demo Navigation' severity: Critical - Incident #25421962, Scenario 'X-AKILA - (Web)' severity: Critical - Incident #25422458, Scenario 'X-Centreon Demo Navigation' severity: Critical - Incident #25423513, Scenario 'X-Centreon Demo Navigation' status: Open, severity: Critical | 'ekara.incidents.current.total.count'=4;;;0; + ... 2 --filter-name='yet not a name' UNKNOWN: No scenarios found, can't search for incidents. Please check filters. + incidents ${tc} [Documentation] Check Iplabel scenarios [Tags] monitoring iplabel restapi @@ -31,6 +62,6 @@ incidents ${tc} Ctn Run Command And Check Result As Strings ${command} ${expected_result} - Examples: tc extra_options expected_result -- - ... 1 --filter-name='Centreon Demo Navigation|AKILA - .Web.' CRITICAL: Incident #25421291, Scenario 'Centreon Demo Navigation' severity: Critical - Incident #25421962, Scenario 'AKILA - (Web)' severity: Critical - Incident #25422458, Scenario 'Centreon Demo Navigation' severity: Critical - Incident #25423513, Scenario 'Centreon Demo Navigation' status: Open, severity: Critical | 'ekara.incidents.current.total.count'=4;;;0; - ... 2 --filter-name='not a name' UNKNOWN: No scenarios found, can't search for incidents. Please check filters. + Examples: tc extra_options expected_result -- + ... 1 ${EMPTY} UNKNOWN: Need to specify --api-key or --api-username/--api-password options. + ... 2 --api-username=username --api-password=password --api-key=PaSsWoRdZ UNKNOWN: Cannot use both --api-key and --api-username/--api-password options. diff --git a/tests/monitoring/iplabel/ekara/restapi/monitoring-iplabel-ekara.json b/tests/monitoring/iplabel/ekara/restapi/monitoring-iplabel-ekara.json index d515ab639..0176f9c93 100644 --- a/tests/monitoring/iplabel/ekara/restapi/monitoring-iplabel-ekara.json +++ b/tests/monitoring/iplabel/ekara/restapi/monitoring-iplabel-ekara.json @@ -136,6 +136,13 @@ "value": "", "invert": false, "operator": "null" + }, + { + "target": "header", + "modifier": "X-api-key", + "value": "", + "invert": false, + "operator": "null" } ], "rulesOperator": "AND", @@ -157,6 +164,102 @@ "databucketID": "", "sendFileAsBody": false, "rules": [ + { + "target": "body", + "modifier": "$.statusFilter.[*]", + "value": "2", + "invert": false, + "operator": "array_includes" + }, + { + "target": "header", + "modifier": "authorization", + "value": "", + "invert": true, + "operator": "null" + }, + { + "target": "header", + "modifier": "X-API-KEY", + "value": "", + "invert": false, + "operator": "null" + } + ], + "rulesOperator": "AND", + "disableTemplating": false, + "fallbackTo404": false, + "default": false, + "crudKey": "id", + "callbacks": [] + }, + { + "uuid": "05977710-18d1-4571-8df1-f36ada2a139f", + "body": "[\n {\n \"scenarioId\": \"09fe2561-315b-470f-a7ac-9c30fbd2e0fb\",\n \"scenarioName\": \"X-AKILA - (Web)\",\n \"currentStatus\": 2,\n \"startTime\": \"2025-12-30T10:21:03Z\"\n },\n {\n \"scenarioId\": \"127a149b-0fa6-4859-820e-9c4db23b6454\",\n \"scenarioName\": \"X-AKILA - (Browser Page Load)\",\n \"currentStatus\": 1,\n \"startTime\": \"2025-12-30T07:20:08Z\"\n },\n {\n \"scenarioId\": \"41d36b91-a4d3-4b00-a3ca-9e4fcf737d30\",\n \"scenarioName\": \"X-Centreon Demo Parcours - Custom views\",\n \"currentStatus\": 1,\n \"startTime\": \"2025-12-29T23:48:39Z\"\n },\n {\n \"scenarioId\": \"425bff8b-51eb-4b68-8529-6258e7b7888c\",\n \"scenarioName\": \"X-Centreon Demo ping Paris\",\n \"currentStatus\": 1,\n \"startTime\": \"2025-12-04T06:15:00Z\"\n },\n {\n \"scenarioId\": \"478a6915-1c00-4e85-9fe2-7d919e28ce88\",\n \"scenarioName\": \"X-Centreon Demo Navigation\",\n \"currentStatus\": 2,\n \"startTime\": \"2025-12-30T10:06:04Z\"\n },\n {\n \"scenarioId\": \"4fa9f25d-ae49-4848-823a-945e7f865f4b\",\n \"scenarioName\": \"X-Centreon Demo ping NA\",\n \"currentStatus\": 8,\n \"startTime\": \"2025-12-30T10:30:21Z\"\n },\n {\n \"scenarioId\": \"7622678e-ffec-49f5-8a67-7d1b4452bff6\",\n \"scenarioName\": \"X-wrong currentstatus, no perfdata\",\n \"currentStatus\": 14,\n \"startTime\": \"2025-12-30T02:00:45Z\"\n },\n {\n \"scenarioId\": \"8d0a798c-1b47-4142-869d-9bdabc9c126c\",\n \"scenarioName\": \"X-Centreon Demo Parcours - Login\",\n \"currentStatus\": 1,\n \"startTime\": \"2025-12-29T23:51:35Z\"\n },\n {\n \"scenarioId\": \"eae701ac-4231-4fc5-94e3-08601ac591e9\",\n \"scenarioName\": \"X-Centreon Demo ping Singapore\",\n \"currentStatus\": 1,\n \"startTime\": \"2025-12-30T10:15:11Z\"\n },\n {\n \"scenarioId\": \"fc6b739e-c18c-40ab-917c-61d20dff830c\",\n \"scenarioName\": \"X-AKILA - Business App\",\n \"currentStatus\": 1,\n \"startTime\": \"2025-12-30T09:30:23Z\"\n },\n {\n \"scenarioId\": \"fe1ca10e-1cf6-45c8-a7e9-b9b85272c086\",\n \"scenarioName\": \"X-AKILA - (API) \",\n \"currentStatus\": 1,\n \"startTime\": \"2025-12-30T10:10:55Z\"\n },\n {\n \"scenarioId\": \"121ca10e-1cf6-45c8-a7e9-b9b85272c086\",\n \"scenarioName\": \"X-unknown Status 0\",\n \"currentStatus\": 0,\n \"startTime\": \"2025-12-30T10:10:55Z\"\n },\n {\n \"scenarioId\": \"121ca10e-1cf6-45c8-a7e9-b9b85272c086\",\n \"scenarioName\": \"X-unknown Status 3\",\n \"currentStatus\": 3,\n \"startTime\": \"2025-12-30T10:10:55Z\"\n },\n {\n \"scenarioId\": \"121ca10e-1cf6-45c8-a7e9-b9b85272c086\",\n \"scenarioName\": \"X-unknown Status 4\",\n \"currentStatus\": 4,\n \"startTime\": \"2025-12-30T10:10:55Z\"\n },\n {\n \"scenarioId\": \"121ca10e-1cf6-45c8-a7e9-b9b85272c086\",\n \"scenarioName\": \"X-unknown Status 5\",\n \"currentStatus\": 5,\n \"startTime\": \"2025-12-30T10:10:55Z\"\n },\n {\n \"scenarioId\": \"121ca10e-1cf6-45c8-a7e9-b9b85272c086\",\n \"scenarioName\": \"X-unknown Status 6\",\n \"currentStatus\": 6,\n \"startTime\": \"2025-12-30T10:10:55Z\"\n },\n {\n \"scenarioId\": \"121ca10e-1cf6-45c8-a7e9-b9b85272c086\",\n \"scenarioName\": \"X-unknown Status 7\",\n \"currentStatus\": 7,\n \"startTime\": \"2025-12-30T10:10:55Z\"\n }\n]", + "latency": 0, + "statusCode": 200, + "label": "Access with api-key authentication", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [ + { + "target": "header", + "modifier": "X-API-KEY", + "value": "PaSsWoRdZ", + "invert": false, + "operator": "equals" + }, + { + "target": "header", + "modifier": "authorization", + "value": "", + "invert": false, + "operator": "null" + }, + { + "target": "body", + "modifier": "$.statusFilter", + "value": "", + "invert": false, + "operator": "null" + } + ], + "rulesOperator": "AND", + "disableTemplating": false, + "fallbackTo404": false, + "default": false, + "crudKey": "id", + "callbacks": [] + }, + { + "uuid": "25c6c5e3-750f-4fc5-9993-e248f81d2490", + "body": "[\n {\n \"scenarioId\": \"478a6915-1c00-4e85-9fe2-7d919e28ce88\",\n \"scenarioName\": \"Centreon Demo Navigation\",\n \"currentStatus\": 3,\n \"startTime\": \"2024-12-30T10:06:04Z\"\n }\n]", + "latency": 0, + "statusCode": 200, + "label": "filter by status for status 3 with API-KEY authentication", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [ + { + "target": "header", + "modifier": "X-API-KEY", + "value": "PaSsWoRdZ", + "invert": false, + "operator": "equals" + }, + { + "target": "header", + "modifier": "Authentication", + "value": "", + "invert": false, + "operator": "null" + }, { "target": "body", "modifier": "$.statusFilter.[*]", @@ -190,6 +293,40 @@ "default": true, "crudKey": "id", "callbacks": [] + }, + { + "uuid": "fa4d5c05-0ac7-4a26-bd25-03f663b4ef73", + "body": "{}", + "latency": 0, + "statusCode": 401, + "label": "", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [ + { + "target": "header", + "modifier": "X-API-KEY", + "value": "", + "invert": true, + "operator": "null" + }, + { + "target": "header", + "modifier": "X-API-KEY", + "value": "PaSsWoRdZ", + "invert": true, + "operator": "equals" + } + ], + "rulesOperator": "AND", + "disableTemplating": false, + "fallbackTo404": false, + "default": false, + "crudKey": "id", + "callbacks": [] } ], "responseMode": null, @@ -784,9 +921,50 @@ "value": "Bearer VeryLongTokenToAuthenticate", "invert": false, "operator": "equals" + }, + { + "target": "header", + "modifier": "X-API-KEY", + "value": "", + "invert": false, + "operator": "null" } ], - "rulesOperator": "OR", + "rulesOperator": "AND", + "disableTemplating": false, + "fallbackTo404": false, + "default": false, + "crudKey": "id", + "callbacks": [] + }, + { + "uuid": "37c2d4dc-e03d-41d8-8e43-f90e283e6361", + "body": "{\n \"kpis\": [\n {\n \"name\": \"Availability\",\n \"order\": 0,\n \"type\": \"User\",\n \"unit\": \"percent\",\n \"label\": \"availability\",\n \"value\": 100\n },\n {\n \"name\": \"Total time for all steps\",\n \"order\": 100,\n \"type\": \"User\",\n \"unit\": \"ms\",\n \"label\": \"time_total_allsteps\",\n \"value\": 4280\n }\n ],\n \"results\": [\n {\n \"planningTime\": \"2024-12-30T10:30:00Z\",\n \"stepId\": \"3\",\n \"metric\": \"time_step\",\n \"duration\": 848,\n \"count\": 1,\n \"value\": 848\n },\n {\n \"planningTime\": \"2024-12-30T10:30:00Z\",\n \"stepId\": \"2\",\n \"metric\": \"time_step\",\n \"duration\": 898,\n \"count\": 1,\n \"value\": 898\n },\n {\n \"planningTime\": \"2024-12-30T10:30:00Z\",\n \"stepId\": \"1\",\n \"metric\": \"time_step\",\n \"duration\": 2534,\n \"count\": 1,\n \"value\": 2534\n }\n ],\n \"siteIds\": [\n {\n \"id\": \"a182ec70-c319-40de-9af0-556877fa64a1\",\n \"name\": \"GSA_POC_2_Win\"\n }\n ],\n \"metrics\": [\n {\n \"mtr_id\": \"time_multi_step\",\n \"mtr_name\": \"Cumulative Time Step\",\n \"mtr_order\": 100,\n \"mtr_type\": \"Cumulative\",\n \"mtr_scn_type\": \"DESKTOP\",\n \"mtr_unit\": \"ms\",\n \"mtr_preferred_metric\": -1,\n \"filterEnabled\": false,\n \"filterDisabledOnMultiStep\": false,\n \"filterDisabledOnAllStep\": false,\n \"filterDisabledOnPartialStep\": false\n },\n {\n \"mtr_id\": \"time_step\",\n \"mtr_name\": \"Time Step\",\n \"mtr_order\": 100,\n \"mtr_type\": \"Technical\",\n \"mtr_scn_type\": \"DESKTOP\",\n \"mtr_unit\": \"ms\",\n \"mtr_preferred_metric\": -1,\n \"filterEnabled\": true,\n \"filterDisabledOnMultiStep\": false,\n \"filterDisabledOnAllStep\": false,\n \"filterDisabledOnPartialStep\": false\n },\n {\n \"mtr_id\": \"time_total\",\n \"mtr_name\": \"Total time for a step\",\n \"mtr_order\": 100,\n \"mtr_type\": \"User\",\n \"mtr_scn_type\": \"DESKTOP\",\n \"mtr_unit\": \"ms\",\n \"mtr_preferred_metric\": -1,\n \"filterEnabled\": null,\n \"filterDisabledOnMultiStep\": null,\n \"filterDisabledOnAllStep\": null,\n \"filterDisabledOnPartialStep\": null\n },\n {\n \"mtr_id\": \"time_total_allsteps\",\n \"mtr_name\": \"Total time for all steps\",\n \"mtr_order\": 100,\n \"mtr_type\": \"User\",\n \"mtr_scn_type\": \"DESKTOP\",\n \"mtr_unit\": \"ms\",\n \"mtr_preferred_metric\": 10,\n \"filterEnabled\": false,\n \"filterDisabledOnMultiStep\": false,\n \"filterDisabledOnAllStep\": false,\n \"filterDisabledOnPartialStep\": false\n }\n ],\n \"retries\": [],\n \"replays\": [],\n \"updates\": [],\n \"runningReplayId\": null,\n \"steps\": [\n {\n \"name\": \"Clean\",\n \"index\": 1,\n \"isNeutral\": true,\n \"isMyBlock\": false\n },\n {\n \"name\": \"Run Chrome\",\n \"index\": 2\n },\n {\n \"name\": \"Dashboard 2\",\n \"index\": 3\n },\n {\n \"name\": \"Dashboard 3\",\n \"index\": 4\n },\n {\n \"name\": \"Clean\",\n \"index\": 5,\n \"isNeutral\": true,\n \"isMyBlock\": false\n }\n ],\n \"infos\": {\n \"active_filter\": [\n {\n \"type\": \"measurementIds\",\n \"items\": [\n \"time_step\",\n \"time_multi_step\",\n \"time_total_allsteps\"\n ]\n }\n ],\n \"plugin_id\": \"DESKTOP\",\n \"plugin_name\": \"Desktop\",\n \"info\": {\n \"hasStep\": true,\n \"showKPI\": false,\n \"hasWaterfall\": false,\n \"showThirdPartyContent\": false\n },\n \"scenarioName\": \"AKILA - (Business App) \",\n \"default_plugin\": false\n },\n \"timelineDetails\": [\n {\n \"status\": 1,\n \"startTime\": \"2024-12-30T10:23:11Z\",\n \"endTime\": \"2024-12-30T10:38:11Z\",\n \"execs\": [\n {\n \"period\": \"PT10M\",\n \"siteId\": \"a182ec70-c319-40de-9af0-556877fa64a1\",\n \"status\": 1,\n \"execTime\": \"2024-12-30T09:30:23Z\",\n \"siteName\": \"GSA_POC_2_Win\",\n \"executionId\": \"22dd8614-400c-40e5-9689-57c48c328055.27\",\n \"planningTime\": \"2024-12-30T09:30:00Z\",\n \"thresholdExceeded\": null\n }\n ]\n }\n ],\n \"aggregate\": \"rowdata\",\n \"emptyResults\": [],\n \"retentionDateExceeded\": false\n}", + "latency": 0, + "statusCode": 200, + "label": "Access with X-API-KEY", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [ + { + "target": "header", + "modifier": "X-API-KEY", + "value": "PaSsWoRdZ", + "invert": false, + "operator": "equals" + }, + { + "target": "header", + "modifier": "Authentication", + "value": "", + "invert": false, + "operator": "null" + } + ], + "rulesOperator": "AND", "disableTemplating": false, "fallbackTo404": false, "default": false, @@ -893,14 +1071,63 @@ "filePath": "", "databucketID": "", "sendFileAsBody": false, - "rules": [], - "rulesOperator": "OR", + "rules": [ + { + "target": "header", + "modifier": "X-API-KEY", + "value": "", + "invert": false, + "operator": "null" + }, + { + "target": "header", + "modifier": "Authentication", + "value": "", + "invert": true, + "operator": "null" + } + ], + "rulesOperator": "AND", "disableTemplating": false, "fallbackTo404": false, "default": true, "crudKey": "id", "callbacks": [] }, + { + "uuid": "92f7fab0-db29-48b4-9aeb-df2079337cbd", + "body": "[\n {\n \"ssr_id\": \"25423513\",\n \"startTime\": \"2024-12-30T23:07:08Z\",\n \"status\": 2,\n \"execList\": [\n {\n \"period\": \"PT1H\",\n \"siteId\": \"8e9538eb-dafe-46fd-9cee-6605fe3e4f60\",\n \"status\": 2,\n \"execTime\": \"2024-12-30T23:07:08Z\",\n \"siteName\": \"Paris (Orange)\",\n \"executionId\": \"1e75b3fb-56b1-4d33-9da9-a4c46e29dfd2.0\",\n \"planningTime\": \"2024-12-30T23:00:00Z\",\n \"thresholdExceeded\": null\n }\n ],\n \"scn_id\": \"478a6915-1c00-4e85-9fe2-7d919e28ce88\",\n \"scnName\": \"X-Centreon Demo Navigation\",\n \"application\": \"X-Centreon\",\n \"severity\": \"Critical\",\n \"duration\": \"PT1H57M7S\",\n \"comments\": false,\n \"dataExclutionId\": null,\n \"startProcessTime\": null,\n \"dataExclutionStatus\": null\n },\n {\n \"ssr_id\": \"25422458\",\n \"startTime\": \"2024-12-30T20:09:21Z\",\n \"endTime\": \"2024-12-30T21:06:49Z\",\n \"status\": 2,\n \"execList\": [\n {\n \"period\": \"PT1H\",\n \"siteId\": \"8e9538eb-dafe-46fd-9cee-6605fe3e4f60\",\n \"status\": 2,\n \"execTime\": \"2024-12-30T20:09:21Z\",\n \"siteName\": \"Paris (Orange)\",\n \"executionId\": \"bbab21cf-031e-46a9-bb3d-03e5a9bd3cce.21\",\n \"planningTime\": \"2024-12-30T20:00:00Z\",\n \"thresholdExceeded\": null\n }\n ],\n \"scn_id\": \"478a6915-1c00-4e85-9fe2-7d919e28ce88\",\n \"scnName\": \"X-Centreon Demo Navigation\",\n \"application\": \"X-Centreon\",\n \"severity\": \"Critical\",\n \"duration\": \"PT57M28S\",\n \"comments\": false,\n \"dataExclutionId\": null,\n \"startProcessTime\": null,\n \"dataExclutionStatus\": null\n },\n {\n \"ssr_id\": \"25421962\",\n \"startTime\": \"2024-12-30T18:52:43Z\",\n \"endTime\": \"2024-12-30T19:07:26Z\",\n \"status\": 2,\n \"execList\": [\n {\n \"period\": \"PT15M\",\n \"siteId\": \"76300f93-1714-4235-aa20-105d0815b4e0\",\n \"status\": 2,\n \"execTime\": \"2024-12-30T18:52:43Z\",\n \"siteName\": \"Paris (Iliad)\",\n \"executionId\": \"37ca8215-f72b-4982-b088-58e68b701b5d.31\",\n \"planningTime\": \"2024-12-30T18:45:00Z\",\n \"thresholdExceeded\": null\n },\n {\n \"period\": \"PT15M\",\n \"siteId\": \"d1c377bf-745f-4d63-b25f-904b16582649\",\n \"status\": 2,\n \"execTime\": \"2024-12-30T19:01:39Z\",\n \"siteName\": \"Paris (SFR)\",\n \"executionId\": \"e34837a6-f807-4347-a454-e505f65be258.32\",\n \"planningTime\": \"2024-12-30T19:00:00Z\",\n \"thresholdExceeded\": null\n }\n ],\n \"scn_id\": \"09fe2561-315b-470f-a7ac-9c30fbd2e0fb\",\n \"scnName\": \"X-AKILA - (Web)\",\n \"application\": \"X-AKILA\",\n \"severity\": \"Critical\",\n \"duration\": \"PT14M43S\",\n \"comments\": false,\n \"dataExclutionId\": null,\n \"startProcessTime\": null,\n \"dataExclutionStatus\": null\n },\n {\n \"ssr_id\": \"25421291\",\n \"startTime\": \"2024-12-30T17:09:44Z\",\n \"endTime\": \"2024-12-30T18:01:19Z\",\n \"status\": 2,\n \"execList\": [\n {\n \"period\": \"PT1H\",\n \"siteId\": \"8e9538eb-dafe-46fd-9cee-6605fe3e4f60\",\n \"status\": 2,\n \"execTime\": \"2024-12-30T17:09:44Z\",\n \"siteName\": \"Paris (Orange)\",\n \"executionId\": \"2ea22968-f89d-4638-838a-47774b0c91f5.18\",\n \"planningTime\": \"2024-12-30T17:00:00Z\",\n \"thresholdExceeded\": null\n }\n ],\n \"scn_id\": \"478a6915-1c00-4e85-9fe2-7d919e28ce88\",\n \"scnName\": \"X-Centreon Demo Navigation\",\n \"application\": \"X-Centreon\",\n \"severity\": \"Critical\",\n \"duration\": \"PT51M35S\",\n \"comments\": false,\n \"dataExclutionId\": null,\n \"startProcessTime\": null,\n \"dataExclutionStatus\": null\n }\n]", + "latency": 0, + "statusCode": 200, + "label": "Access with API KEY", + "headers": [], + "bodyType": "INLINE", + "filePath": "", + "databucketID": "", + "sendFileAsBody": false, + "rules": [ + { + "target": "header", + "modifier": "X-api-key", + "value": "PaSsWoRdZ", + "invert": false, + "operator": "equals" + }, + { + "target": "header", + "modifier": "Authentication", + "value": "", + "invert": false, + "operator": "null" + } + ], + "rulesOperator": "AND", + "disableTemplating": false, + "fallbackTo404": false, + "default": false, + "crudKey": "id", + "callbacks": [] + }, { "uuid": "a2e22546-df45-4513-9163-3ef7520bc17d", "body": "[]", diff --git a/tests/monitoring/iplabel/ekara/restapi/scenarios.robot b/tests/monitoring/iplabel/ekara/restapi/scenarios.robot index 6031d7712..36ff9d1d8 100644 --- a/tests/monitoring/iplabel/ekara/restapi/scenarios.robot +++ b/tests/monitoring/iplabel/ekara/restapi/scenarios.robot @@ -13,19 +13,19 @@ ${MOCKOON_JSON} ${CURDIR}${/}monitoring-iplabel-ekara.json ${cmd} ${CENTREON_PLUGINS} ... --plugin=apps::monitoring::iplabel::ekara::restapi::plugin ... --hostname=localhost -... --api-username='username' -... --api-password='password' ... --port='3000' ... --proto='http' *** Test Cases *** -scenario ${tc} +scenario-username ${tc} [Documentation] Check Iplabel scenarios [Tags] monitoring iplabel restapi ${command} Catenate ... ${cmd} ... --mode=scenarios + ... --api-username='username' + ... --api-password='password' ... ${extra_options} Ctn Run Command And Check Result As Strings ${command} ${expected_result} @@ -52,3 +52,33 @@ scenario ${tc} ... 16 --filter-name='unknown Status 6' --output-ignore-perfdata UNKNOWN: Scenario 'unknown Status 6': status: Stopped (6) ... 17 --filter-name='AKILA - .Web.' --curl-opt='CURLOPT_HTTPHEADER => [test: 2]' --curl-opt='CURLOPT_HTTPHEADER => [ Authorization: Bearer VeryLongTokenToAuthenticate]' CRITICAL: Scenario 'AKILA - (Web)': status: Failure (2) | 'AKILA - (Web)#scenario.availability.percentage'=64.48%;;;0;100 'AKILA - (Web)#scenario.time.allsteps.total.milliseconds'=4031ms;;;0; 'AKILA - (Web)~Home#scenario.step.time.milliseconds'=3862ms;;;0; 'AKILA - (Web)~Dashboard v2#scenario.step.time.milliseconds'=215ms;;;0; 'AKILA - (Web)~Dashboard v3#scenario.step.time.milliseconds'=68ms;;;0; +scenario-apikey ${tc} + [Documentation] Check Iplabel scenarios + [Tags] monitoring iplabel restapi + + ${command} Catenate + ... ${cmd} + ... --mode=scenarios + ... --api-key='PaSsWoRdZ' + ... ${extra_options} + + Ctn Run Command And Check Result As Strings ${command} ${expected_result} + + Examples: tc extra_options expected_result -- + ... 1 --filter-name='X-AKILA - Business App' OK: Scenario 'X-AKILA - Business App': status: Success (1), availability: 100%, time total all steps: 4280ms - All steps are ok | 'X-AKILA - Business App#scenario.availability.percentage'=100%;;;0;100 'X-AKILA - Business App#scenario.time.allsteps.total.milliseconds'=4280ms;;;0; 'X-AKILA - Business App~Run Chrome#scenario.step.time.milliseconds'=2534ms;;;0; 'X-AKILA - Business App~Dashboard 2#scenario.step.time.milliseconds'=898ms;;;0; 'X-AKILA - Business App~Dashboard 3#scenario.step.time.milliseconds'=848ms;;;0; + ... 9 --api-key='wrongkey' UNKNOWN: API key is not valid. + +scenario ${tc} + [Documentation] Check Iplabel scenarios + [Tags] monitoring iplabel restapi + + ${command} Catenate + ... ${cmd} + ... --mode=scenarios + ... ${extra_options} + + Ctn Run Command And Check Result As Strings ${command} ${expected_result} + + Examples: tc extra_options expected_result -- + ... 1 ${EMPTY} UNKNOWN: Need to specify --api-key or --api-username/--api-password options. + ... 2 --api-username=username --api-password=password --api-key=PaSsWoRdZ UNKNOWN: Cannot use both --api-key and --api-username/--api-password options.