PluginProbe
WebTotem Security / 2.4.3
WebTotem Security v2.4.3
3.0.1 3.0.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 2.0 2.1 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.1 2.2.2 2.2.3 2.2.4 All 109 releases
wt-security / lib / API.php

API.php in WebTotem Security 2.4.3, at lib/API.php

932 lines 34.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('WEBTOTEM_INIT') || WEBTOTEM_INIT !== true) {
4 if (!headers_sent()) {
5 header('HTTP/1.1 403 Forbidden');
6 }
7 die("Protected By WebTotem!");
8 }
9
10 /**
11 * WebTotem API class.
12 *
13 * Mostly contains wrappers for API methods. Check and send methods.
14 *
15 * @version 1.0
16 * @copyright (C) 2022 WebTotem team (http://wtotem.com)
17 * @license GNU/GPL: http://www.gnu.org/copyleft/gpl.html
18 */
19 class WebTotemAPI extends WebTotem {
20
21 /**
22 * Method for getting a auth token.
23 *
24 * @param string $api_key
25 * Application programming interface key.
26 *
27 * @return bool|string
28 * Returns auth status
29 */
30 public static function auth($api_key) {
31 $domain = WEBTOTEM_SITE_DOMAIN;
32
33 $payload = '{"query":"mutation{ guest{ apiKeys{ auth(apiKey:\"' . $api_key . '\", source:\"' . $domain . '\"),{ token{ value, refreshToken, expiresIn } } } } }"}';
34 $result = self::sendRequest($payload, FALSE, TRUE);
35
36 if (isset($result['data']['guest']['apiKeys']['auth']['token']['value'])) {
37 $auth_token = $result['data']['guest']['apiKeys']['auth']['token'];
38 WebTotemOption::login(['token' => $auth_token, 'api_key' => $api_key]);
39 return 'success';
40 } elseif($result['errors'][0]['message'] == 'INVALID_API_KEY') {
41 WebTotemOption::logout();
42 }
43
44 return FALSE;
45 }
46
47
48 /**
49 * Get site info from API server.
50 *
51 * @param string $attempt
52 * Is the request an attempt to get host data.
53 *
54 * @return array
55 * Returns host data.
56 */
57 public static function siteInfo($attempt = FALSE) {
58
59 if(self::isMultiSite()){
60 $host['id'] = WebTotemOption::getSessionOption('host_id');
61
62 if ($host['id']) {
63 return $host;
64 }
65 }
66
67 $host = WebTotemOption::getHost();
68
69 if ($host['id']) {
70 return $host;
71 }
72
73 $all_sites = self::getSites(null, 0);
74 if(self::isMultiSite()) {
75 $sites = get_sites();
76 foreach ($sites as $site){
77 $domain = untrailingslashit($site->domain . $site->path);
78 self::addSite($domain, $all_sites);
79 }
80
81 if (!$attempt) {
82 return self::siteInfo(TRUE);
83 }
84 }
85 else {
86 $domain = WEBTOTEM_SITE_DOMAIN;
87 return self::addSite($domain, $all_sites);
88 }
89
90 return [];
91 }
92
93 /**
94 * Method for adding a site to the WebTotem platform.
95 *
96 * @param string $domain
97 * Domain to add.
98 * @param array $all_sites
99 * Array with site data on the WebTotem platform.
100 *
101 * @return array
102 * Returns host data.
103 */
104 public static function addSite( $domain, $all_sites) {
105
106 if(function_exists('idn_to_utf8')){
107 $domain = idn_to_utf8($domain);
108 }
109
110 // Checking if the site has been added to the WebTotem.
111 foreach ($all_sites['edges'] as $site){
112 $site = $site['node'];
113 // If it added, save site data to DB.
114 if($site['hostname'] == $domain or 'www.' . $site['hostname'] == $domain){
115 WebTotemOption::setHost($site['hostname'], $site['id']);
116 return [
117 'id' => $site['id'],
118 'name' => $site['hostname'],
119 ];
120 }
121 }
122
123 // If the site is not added then try to add.
124 $payload = '{"variables":{"input":{"title":"' . $domain . '","hostname":"' . $domain . '","configs":{"scheme":"http","port":80,"wa":{},"dec":{},"ps":{}}}},"query":"mutation ($input: CreateSiteInput) { auth { sites { create(input: $input) { id hostname title } } } }"}';
125 $add_site = self::sendRequest($payload, TRUE);
126 if (isset($add_site['errors'])) {
127 WebTotemOption::setNotification('error', __('Failed to add the site to the WebTotem platform.', 'wtotem'));
128 }
129 else {
130 if($host = $add_site['data']['auth']['sites']['create']) {
131 // If it added, save site ID.
132 WebTotemOption::setHost($host['title'], $host['id']);
133 return [
134 'id' => $host['id'],
135 'name' => $host['title'],
136 ];
137 }
138 }
139 return [];
140 }
141
142 /**
143 * Get all sites from API.
144 *
145 * @param string $cursor
146 * Mark for loading data.
147 * @param string $limit
148 * Limit of sites to loading.
149 *
150 * @return array
151 * Returns host data.
152 */
153 public static function getSites($cursor = null, $limit = 15, $filter = false) {
154 $cursor = ($cursor == null) ? 'null' : '\"' . $cursor . '\"';
155 if(!$filter) {
156 $filter = ($limit === 0) ? '' : 'pagination:{ first: ' . $limit . ', cursor: ' . $cursor . ' }';
157 }
158
159 $payload = '{"query":"query getSites { auth { viewer { sites { ...sites } } } } fragment sites on SiteQueries { list(filter: { ' . $filter . ' }) { pageInfo{ hasNextPage endCursor } edges { node { id hostname title createdAt ssl { status } availability { status } reputation { status } ports { status } deface { status } domain { status } antivirus { status } firewall { status } maliciousScript { stack { name } } } } } }"}';
160 $result = self::sendRequest($payload, true);
161
162 if (isset($result['data']['auth']['viewer']['sites']['list']['edges'])) {
163 return $result['data']['auth']['viewer']['sites']['list'];
164 }
165
166 return [];
167 }
168
169 /**
170 * Method to get the agents file names and AM file link.
171 *
172 * @param string $host_id
173 * Host id on WebTotem.
174 *
175 * @return array
176 * Returns agents files data.
177 */
178 public static function getAgentsFiles($host_id) {
179
180 if(WebTotem::isMultiSite()){
181 $all_hosts = WebTotemOption::getOption('all_hosts');
182 $siteIdsArray = array_values($all_hosts);
183 $siteIds = addslashes(WebTotem::convertArrayToString($siteIdsArray));
184
185 $payload = '{"query":"mutation { auth { am { installMultisite(mainSiteId: \"' . $host_id . '\", siteIds: [' . $siteIds . ']){ downloadLink, amFilename, wafFilename, avFilename } } } }"}';
186 $response = self::sendRequest($payload, TRUE);
187 return $response['data']['auth']['am']['installMultisite'];
188 }
189 else {
190 $payload = '{"query":"mutation { auth { am { install(siteId: \"' . $host_id . '\"){ downloadLink, amFilename, wafFilename, avFilename } } } }"}';
191 $response = self::sendRequest($payload, TRUE);
192 return $response['data']['auth']['am']['install'];
193 }
194 }
195
196 /**
197 * Add secondary MultiSite host.
198 *
199 * @param $main_host_id
200 * Host id of the main site in MultiSite network.
201 * @param $new_sites
202 * An array with sites to add.
203 *
204 * @return void.
205 */
206 public static function addMultiSiteNewSites($new_sites){
207 $main_host = WebTotemOption::getMainHost();
208 foreach ($new_sites as $site){
209 $all_sites = self::getSites(null, 0);
210 $host = self::addSite($site, $all_sites);
211 if(key_exists('id', $host)){
212 $payload = '{"query":"mutation { auth { am { addMultisiteHost(mainSiteId: \"' . $main_host['id'] . '\", siteId: \"' . $host['id'] . '\") } } }"}';
213 self::sendRequest($payload, TRUE);
214 }
215 }
216 }
217
218 /**
219 * Remove secondary MultiSite host.
220 *
221 * @param $host_id
222 * Host id on WebTotem.
223 *
224 * @return bool
225 * Returns result removing host.
226 */
227 public static function removeMultiSiteHost($host_id){
228 $payload = '{"query":"mutation { auth { am { removeMultisiteHost(siteId: \"' . $host_id . '\") } } }"}';
229 $response = self::sendRequest($payload, TRUE);
230 return $response['data']['auth']['am']['removeSecondaryMultisiteHost'];
231 }
232
233 /**
234 * Method to get agents (AM, WAF, AV) statuses.
235 *
236 * @param string $host_id
237 * Host id on WebTotem.
238 *
239 * @return array
240 * Returns agents statuses data.
241 */
242 public static function getAgentsStatusesFromAPI($host_id) {
243 $payload = '{"query":"query ($id: ID!) { auth { viewer { sites { one(id: $id) { agentManager { statuses { am { status } av { status } waf { status } } } } } } } }", "variables":{"id":"' . $host_id . '"}}';
244 $response = self::sendRequest($payload, TRUE);
245
246 if (isset($response['data']['auth']['viewer']['sites']['one']['agentManager']['statuses'])) {
247 return $response['data']['auth']['viewer']['sites']['one']['agentManager']['statuses'];
248 }
249
250 return [];
251 }
252
253 /**
254 * Method to get user time zone.
255 *
256 * @return string|bool
257 * Returns time zone data.
258 */
259 public static function getTimeZone() {
260 $payload = '{"query":"query { auth { viewer{ timezone } } } "}';
261 $response = self::sendRequest($payload, TRUE);
262
263 if (isset($response['data']['auth']['viewer']['timezone'])) {
264 return $response['data']['auth']['viewer']['timezone'];
265 }
266 return FALSE;
267 }
268
269 /**
270 * Method for get all the site security data.
271 *
272 * @param string $host_id
273 * Host id on WebTotem.
274 * @param int|array $days
275 * For what period data is needed.
276 *
277 * @return array
278 * Returns all data.
279 */
280 public static function getAllData($host_id, $days = 7) {
281 $language = WebTotem::getLanguage();
282 $period = WebTotem::getPeriod($days);
283
284 $payload = '{"query":"query($id: ID!, $dateRange: DateRangeInput!, $language: Language!, $dateRangeWeek: DateRangeInput!, $wafLogFilter: WafLogFilter!) { auth { viewer { sites { one(id: $id) { ports { status ip tcp ignorePorts lastTest { time } } availability { status lastTest { time } responseTime downTime(dateRange: $dateRange) percent(dateRange: $dateRange) } deface { status lastTest { time } words count } domain { status registrar owner email createdDate expiredDate } ports { status lastTest { time } ip tcp country } ssl { status daysLeft expiryDate issueDate } reputation { status lastTest { time } virusList { virus{ type path } antiVirus } } firewall { lastTest { time } logs(wafLogFilter: $wafLogFilter){ edges{ node{ type blocked payload ip location{ country{ nameEn } } time request status country category } } } map(dateRange: $dateRange) { attacks, country } status chart(dateRange: $dateRange) { time attacks blocked } report(dateRange: $dateRange) { time attacks ip } } serverStatus { info { phpVersion phpServerUser phpServerSoftware phpGatewayInterface phpServerProtocol osInfo cpuCount cpuModel CpuFreq cpuFamily lsCpu maxExecTime mathLibraries } ramChart(dateRange: $dateRangeWeek){ total value time } cpuChart(dateRange: $dateRangeWeek){ value time } discUsage{ total free } status } maliciousScript { lastTest { time } status } scoring( language: $language ){ score lastTest{ time } result{ ip country isHigherThan }} agentManager{ createdAt } antivirus { status stats { changed deleted scanned infected error } lastTest { time } isFirstCheck } } } } } }","variables":{"id":"' . $host_id . '","dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '}, "dateRangeWeek":{"to":' . $period['to'] . ',"from":' . $period['from'] . '}, "wafLogFilter": {"dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '},"order":{"direction":"DESC","field":"time"},"pagination":{"first": 10,"cursor":null}}, "language":"' . $language . '"}}';
285 $response = self::sendRequest($payload, TRUE);
286
287 if (isset($response['data']['auth']['viewer']['sites']['one'])) {
288 return $response['data']['auth']['viewer']['sites']['one'];
289 }
290
291 return [];
292 }
293
294 /**
295 * Method to get firewall data.
296 *
297 * @param string $host_id
298 * Host id on WebTotem.
299 * @param int $limit
300 * Limit on the number of records.
301 * @param string $cursor
302 * Mark for loading data.
303 * @param int|array $days
304 * For what period data is needed.
305 *
306 * @return array
307 * Returns firewall data.
308 */
309 public static function getFirewall($host_id, $limit = 20, $cursor = NULL, $days = 365) {
310 $period = WebTotem::getPeriod($days);
311 $cursor = ($cursor == NULL) ? 'null' : '"' . $cursor . '"';
312
313 $payload = '{"query":"query($id: ID!, $wafLogFilter: WafLogFilter!, $dateRange: DateRangeInput!) { auth { viewer { sites { one(id: $id) { firewall { lastTest { time } status map(dateRange: $dateRange) { attacks, country, location { country { nameEn } } } chart(dateRange: $dateRange) { time attacks blocked } ...FirewallLogFragment } agentManager { createdAt } } } } } } fragment FirewallLogFragment on Waf { logs(wafLogFilter: $wafLogFilter) { edges { cursor node { type blocked payload ip location { country { nameEn } } time request status country category } } pageInfo { endCursor hasNextPage } } }", "variables":{"dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '},"id":"' . $host_id . '","wafLogFilter":{"dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '},"order":{"direction":"DESC","field":"time"},"pagination":{"first":' . $limit . ',"cursor":' . $cursor . '}}} }';
314 $response = self::sendRequest($payload, TRUE);
315
316 if (isset($response['data']['auth']['viewer']['sites']['one'])) {
317 return $response['data']['auth']['viewer']['sites']['one'];
318 }
319
320 return [];
321 }
322
323 /**
324 * Method to get firewall chart data.
325 *
326 * @param string $host_id
327 * Host id on WebTotem.
328 * @param int $days
329 * For what period data is needed.
330 *
331 * @return array
332 * Returns firewall chart data.
333 */
334 public static function getFirewallChart($host_id, $days = 7) {
335 $period = WebTotem::getPeriod($days);
336
337 $payload = '{ "query":"query($id: ID!, $dateRange: DateRangeInput!) { auth { viewer { sites { one(id: $id) { firewall { lastTest { time } status map(dateRange: $dateRange) { attacks, country, location { country { nameEn } } } chart(dateRange: $dateRange) { time attacks blocked } } } } } } }", "operationName":null,"variables":{"id":"' . $host_id . '","dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '} } }';
338 $response = self::sendRequest($payload, TRUE);
339
340 if (isset($response['data']['auth']['viewer']['sites']['one']['firewall'])) {
341 return $response['data']['auth']['viewer']['sites']['one']['firewall'];
342 }
343
344 return [];
345 }
346
347 /**
348 * Method to set firewall settings.
349 *
350 * @param string $host_id
351 * Host id on WebTotem.
352 * @param array $settings
353 * User-specified settings.
354 *
355 * @return array
356 * Returns information whether the request was successful.
357 */
358 public static function setFirewallSettings($host_id, array $settings) {
359 $payload = '{"variables":{"input": {"siteId": "' . $host_id . '", "gdn": ' . $settings['gdn'] . ', "dosProtection": ' . $settings['dosProtection'] . ', "dosLimit": ' . $settings['dosLimit'] . ', "loginAttemptsProtection": ' . $settings['loginAttemptsProtection'] . ', "loginAttemptsLimit": ' . $settings['loginAttemptsLimit'] . '}},"query":"mutation WafSettings($input: WafSettingsInput!) { auth { sites { waf{ settings(input: $input) { gdn dosProtection loginAttemptsProtection dosLimit loginAttemptsLimit } } } } }"}';
360 return self::sendRequest($payload, TRUE);
361 }
362
363 /**
364 * Method to get antivirus data.
365 *
366 * @param array $params
367 * Parameters for filtering data.
368 *
369 * @return array
370 * Returns antivirus data.
371 */
372 public static function getAntivirus(array $params) {
373 $cursor = ($params['cursor']) ? '"' . $params['cursor'] . '"' : 'null';
374 $event = ($params['event']) ? '"' . $params['event'] . '"' : '"new"';
375 $permissions = ($params['permissions']) ? ' "permissionsChanged":true, ' : '';
376 $period = WebTotem::getPeriod($params['days']);
377
378 $payload = '{"operationName":null,"variables":{"id":"' . $params['host_id'] . '","avLogFilter":{' . $permissions . '"event":' . $event . ', "dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '},"order":{"direction":"DESC","field":"time"},"pagination":{"first":' . $params['limit'] . ',"cursor":' . $cursor . '}}},"query":"query ($id: ID!, $avLogFilter: AvLogFilter!) { auth { viewer { sites { one(id: $id) { id ... on Site { configs { ... on AvConfig { isActive id } } } antivirus { quarantine{ id path date } status log(avLogFilter: $avLogFilter) { edges { node { filePath event signatures time permissions permissionsChanged } } pageInfo { endCursor hasNextPage __typename } } lastTest { time } stats { changed deleted scanned infected } } } } } } }"}';
379 $response = self::sendRequest($payload, TRUE);
380
381 if (isset($response['data']['auth']['viewer']['sites']['one']['antivirus'])) {
382 return $response['data']['auth']['viewer']['sites']['one']['antivirus'];
383 }
384 return [];
385 }
386
387 /**
388 * Method to get antivirus last test.
389 *
390 * @param string $host_id
391 * Host id on WebTotem.
392 *
393 * @return array
394 * Returns antivirus last test data.
395 */
396 public static function getAntivirusLastTest($host_id) {
397
398 $payload = '{"variables":{"id":"' . $host_id . '"},"query":"query ($id: ID!) { auth { viewer { sites { one(id: $id) { antivirus { status lastTest { time } } } } } } }"}';
399 $response = self::sendRequest($payload, TRUE);
400
401 if (isset($response['data']['auth']['viewer']['sites']['one']['antivirus'])) {
402 return $response['data']['auth']['viewer']['sites']['one']['antivirus'];
403 }
404 return [];
405 }
406
407 /**
408 * Method to force check services.
409 *
410 * @param string $host_id
411 * Host id on WebTotem.
412 * @param string $service
413 * Service that needs to be checked.
414 *
415 * @return array
416 * Returns information whether the request was successful.
417 */
418 public static function forceCheck($host_id, $service) {
419 $payload = '{"variables":{"id":"' . $host_id . '","service":"' . $service . '"},"query":"mutation ($id: ID!, $service: ForceCheckService!) { auth { sites { forceCheck(siteId: $id, service: $service) } } }"} ';
420 return self::sendRequest($payload, TRUE);
421 }
422
423 /**
424 * Method to export antivirus report.
425 *
426 * @param string $host_id
427 * Host id on WebTotem.
428 * @param int|array $days
429 * For what period data is needed.
430 *
431 * @return array
432 * Returns information whether the request was successful.
433 */
434 public static function avExport($host_id, $days = 30) {
435 $period = WebTotem::getPeriod($days);
436 $payload = '{"variables":{ "input":{"siteId":"' . $host_id . '", "dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '} }},"query":"mutation ($input: AvLogExportInput!) { auth { sites { av { export(input: $input) } } } }"} ';
437 return self::sendRequest($payload, TRUE);
438 }
439
440 /**
441 * Method to get quarantine data.
442 *
443 * @param string $host_id
444 * Host id on WebTotem.
445 *
446 * @return array
447 * Returns quarantine data.
448 */
449 public static function getQuarantineList($host_id) {
450 $payload = '{"query":"query{ auth{ viewer{ sites{ one(id:\"' . $host_id . '\"){ antivirus{ quarantine{ id path date } } } } } } } "}';
451 $response = self::sendRequest($payload, TRUE);
452
453 if (isset($response['data']['auth']['viewer']['sites']['one']['antivirus']['quarantine'])) {
454 return $response['data']['auth']['viewer']['sites']['one']['antivirus']['quarantine'];
455 }
456 return [];
457 }
458
459 /**
460 * Method to move file to quarantine.
461 *
462 * @param string $host_id
463 * Host id on WebTotem.
464 * @param string $path
465 * Path to the file.
466 *
467 * @return array
468 * Returns information whether the request was successful.
469 */
470 public static function moveToQuarantine($host_id, $path) {
471 $payload = '{"query":"mutation{ auth{ sites{ av{ moveToQuarantine(input:{ siteId:\"' . $host_id . '\", path:\"' . $path . '\" }) } } } } "}';
472 return self::sendRequest($payload, TRUE);
473 }
474
475 /**
476 * Method to move file from quarantine.
477 *
478 * @param string $id
479 * Id assigned to the file.
480 *
481 * @return array
482 * Returns information whether the request was successful.
483 */
484 public static function moveFromQuarantine($id) {
485 $payload = '{"query":"mutation{ auth{ sites{ av{ moveFromQuarantine(id: \"' . $id . '\") } } } } "}';
486 return self::sendRequest($payload, TRUE);
487 }
488
489 /**
490 * Method to get server status data.
491 *
492 * @param string $host_id
493 * Host id on WebTotem.
494 * @param int|array $days
495 * For what period data is needed.
496 *
497 * @return array
498 * Returns server status data.
499 */
500 public static function getServerStatusData($host_id, $days = 7) {
501 $period = WebTotem::getPeriod($days);
502 $payload = '{ "query":"query($id: ID!, $dateRange: DateRangeInput!) { auth { viewer { sites { one(id: $id) { serverStatus { ramChart(dateRange: $dateRange){ total value time } cpuChart(dateRange: $dateRange){ value time } } } } } } }", "variables":{"id":"' . $host_id . '","dateRange":{"to":' . $period['to'] . ',"from":' . $period['from'] . '} } }';
503
504 $response = self::sendRequest($payload, TRUE);
505
506 if (isset($response['data']['auth']['viewer']['sites']['one']['serverStatus'])) {
507 return $response['data']['auth']['viewer']['sites']['one']['serverStatus'];
508 }
509
510 return [];
511 }
512
513 /**
514 * Method to remove port from ignore list.
515 *
516 * @param string $host_id
517 * Host id on WebTotem.
518 * @param string $port
519 * User specified port.
520 *
521 * @return array
522 * Returns information whether the request was successful.
523 */
524 public static function removeIgnorePort($host_id, $port) {
525 $payload = '{"variables":{ "input": { "siteId": "' . $host_id . '", "port":' . $port . '} },"query":"mutation($input: IgnorePortInput!) { auth { sites { ps { removeIgnorePort(input: $input) } } } }"} ';
526 return self::sendRequest($payload, TRUE);
527 }
528
529 /**
530 * Method to add port to ignore list.
531 *
532 * @param string $host_id
533 * Host id on WebTotem.
534 * @param string $port
535 * User specified port.
536 *
537 * @return array
538 * Returns information whether the request was successful.
539 */
540 public static function addIgnorePort($host_id, $port) {
541 $payload = '{"variables":{ "input": { "siteId": "' . $host_id . '", "port":' . (int) $port . '} },"query":"mutation($input: IgnorePortInput!) { auth { sites { ps { addIgnorePort(input: $input) } } } }"} ';
542 return self::sendRequest($payload, TRUE);
543 }
544
545 /**
546 * Method to get all ports list.
547 *
548 * @param string $host_id
549 * Host id on WebTotem.
550 *
551 * @return array
552 * Returns ports data.
553 */
554 public static function getAllPortsList($host_id) {
555 $payload = '{"query":"query($id: ID!) { auth { viewer { sites { one(id: $id) { ports { status ip tcp ignorePorts lastTest { time } } } } } } } ","variables":{"id":"' . $host_id . '"}}';
556
557 $response = self::sendRequest($payload, TRUE);
558
559 if (isset($response['data']['auth']['viewer']['sites']['one']['ports'])) {
560 return $response['data']['auth']['viewer']['sites']['one']['ports'];
561 }
562
563 return [];
564 }
565
566 /**
567 * Method to get all reports.
568 *
569 * @param string $host_id
570 * Host id on WebTotem.
571 * @param int $limit
572 * Limit on the number of records.
573 * @param string $cursor
574 * Mark for loading data.
575 *
576 * @return array
577 * Returns reports data.
578 */
579 public static function getAllReports($host_id, $limit = 10, $cursor = NULL) {
580 $cursor = ($cursor == NULL) ? 'null' : '"' . $cursor . '"';
581 $payload = '{"variables":{"filter": { "order": { "direction": "DESC", "field": "created_at"}, "siteId":"' . $host_id . '", "pagination":{"first":' . $limit . ', "cursor":' . $cursor . '} } },"query":"query ReportsQuery($filter: ReportListFilter!) { auth { viewer { reports { list(filter: $filter) { edges { node { id site { hostname } createdAt wa dc ps rc sc av waf } cursor } pageInfo { endCursor hasNextPage } } } } } }"}';
582 $response = self::sendRequest($payload, TRUE);
583
584 if (isset($response['data']['auth']['viewer']['reports']['list']['edges'])) {
585 return $response['data']['auth']['viewer']['reports']['list'];
586 }
587
588 return [];
589 }
590
591 /**
592 * Method to generate report.
593 *
594 * @param string $host_id
595 * Host id on WebTotem.
596 * @param int|array $days
597 * For what period data is needed.
598 * @param array $services
599 * User-specified module settings.
600 *
601 * @return string|bool
602 * Returns report download link.
603 */
604 public static function generateReport($host_id, $days, array $services) {
605 $period = WebTotem::getPeriod($days);
606 $language = WebTotem::getLanguage();
607
608 $payload = '{"query":"query ($input: GenerateReportInput) { auth { viewer { reports { generate(input: $input) } } } }", "variables":{ "input": { "siteId": "' . $host_id . '", "from": ' . $period['from'] . ', "to": ' . $period['to'] . ', "wa": ' . $services['wa'] . ', "dc": ' . $services['dc'] . ', "ps": ' . $services['ps'] . ', "rc": ' . $services['rc'] . ', "sc": ' . $services['sc'] . ', "av": ' . $services['av'] . ', "waf": ' . $services['waf'] . ', "language": "' . $language . '" } } }';
609 $response = self::sendRequest($payload, TRUE);
610
611 if (isset($response['data']['auth']['viewer']['reports']['generate'])) {
612 return $response['data']['auth']['viewer']['reports']['generate'];
613 }
614
615 return FALSE;
616 }
617
618 /**
619 * Method to download report.
620 *
621 * @param string $id
622 * Assigned to the report.
623 *
624 * @return string|bool
625 * Returns report download link.
626 */
627 public static function downloadReport($id) {
628 $payload = '{"query": "query { auth { viewer { reports { download(id: \"' . $id . '\") } } } }"}';
629 $response = self::sendRequest($payload, TRUE);
630
631 if (isset($response['data']['auth']['viewer']['reports']['download'])) {
632 return $response['data']['auth']['viewer']['reports']['download'];
633 }
634
635 return FALSE;
636 }
637
638 /**
639 * Method to get configs data.
640 *
641 * @param string $host_id
642 * Host id on WebTotem.
643 *
644 * @return array|bool
645 * Returns configs data.
646 */
647 public static function getConfigs($host_id) {
648 $payload = '{"query":"query{ auth{ viewer{ sites{ one(id:\"' . $host_id . '\"){ configs{ ... on WaConfig { id service isActive notifications } ... on WafConfig { id service isActive notifications } ... on AvConfig { id service isActive notifications } ... on DcConfig { id service isActive notifications } ... on DecConfig { id service isActive } ... on RcConfig { id service isActive notifications} ... on CmsConfig { id service isActive } ... on PsConfig { id service isActive notifications } ... on SsConfig { id service isActive } ... on ScConfig { id service isActive } } } } } } } "}';
649 $response = self::sendRequest($payload, TRUE);
650
651 if (isset($response['data']['auth']['viewer']['sites']['one']['configs'])) {
652 return $response['data']['auth']['viewer']['sites']['one']['configs'];
653 }
654
655 return FALSE;
656 }
657
658 /**
659 * Method to toggle modules config.
660 *
661 * @param string $service_id
662 * Service id that we enable or disable.
663 *
664 * @return string|bool
665 * Returns information whether the request was successful.
666 */
667 public static function toggleConfigs($service_id) {
668 $payload = '{"query":"mutation{ auth{ configs{ toggle(id: \"' . $service_id . '\"){ ... on WaConfig { service isActive } ... on AvConfig { service isActive } ... on DcConfig { service isActive } ... on DecConfig { service isActive } ... on RcConfig { service isActive } ... on CmsConfig { service isActive } ... on PsConfig { service isActive } ... on WafConfig { service isActive } } } } } "}';
669 $response = self::sendRequest($payload, TRUE);
670
671 if (isset($response['data']['auth']['configs']['toggle'])) {
672 return $response['data']['auth']['configs']['toggle'];
673 }
674
675 return FALSE;
676 }
677
678 /**
679 * Method to toggle modules notification.
680 *
681 * @param string $host_id
682 * Host id on WebTotem.
683 * @param string $service
684 * Service id in which we enable or disable notifications.
685 *
686 * @return string|bool
687 * Returns information whether the request was successful.
688 */
689 public static function toggleNotifications($host_id, $service) {
690 $payload = '{"query":"mutation{ auth{ sites{ toggleNotifications(siteId: \"' . $host_id . '\", service: ' . $service . ') } } }"}';
691 $response = self::sendRequest($payload, TRUE);
692
693 if (isset($response['data']['auth']['sites']['toggleNotifications'])) {
694 return $response;//['data']['auth']['sites']['toggleNotifications'];
695 }
696
697 return FALSE;
698 }
699
700 /**
701 * Method to get allow/deny ip list.
702 *
703 * @param string $host_id
704 * Host id on WebTotem.
705 *
706 * @return array|bool
707 * Returns ip allow/deny lists.
708 */
709 public static function getIpLists($host_id) {
710 $payload = '{"variables":{ "id": "' . $host_id . '" },"query":"query($id: ID!) { auth { viewer { sites{ one(id: $id){ firewall{ blackList{ id ip createdAt } whiteList{ id ip createdAt } settings{ gdn dosProtection dosLimit loginAttemptsProtection loginAttemptsLimit } } } } } } }"} ';
711 $response = self::sendRequest($payload, TRUE);
712
713 if (isset($response['data']['auth']['viewer']['sites']['one']['firewall'])) {
714 return $response['data']['auth']['viewer']['sites']['one']['firewall'];
715 }
716
717 return [];
718 }
719
720 /**
721 * Method to add ip to allow/deny list.
722 *
723 * @param string $host_id
724 * Host id on WebTotem.
725 * @param string $ips
726 * Ip address list.
727 * @param string $list
728 * Allow or deny list.
729 *
730 * @return bool
731 * Returns information whether the request was successful.
732 */
733 public static function addIpToList($host_id, $ips, $list) {
734
735 if ($ips) {
736 $ips = WebTotem::convertIpListForApi($ips);
737 $payload = '{"variables":{ "input": { "siteId": "' . $host_id . '", "ips": ' . $ips . ', "color": "' . $list . '" } }, "query":"mutation($input: WafListInput!) { auth { sites { waf { addToList(input: $input){ status invalidIPs} } } } }"} ';
738 $response = self::sendRequest($payload, TRUE);
739
740 if (isset($response['data']['auth']['sites']['waf']['addToList'])) {
741 return $response['data']['auth']['sites']['waf']['addToList'];
742 }
743 }
744
745 return FALSE;
746 }
747
748 /**
749 * Method to remove ip from allow/deny list by id.
750 *
751 * @param string $id
752 * Id assignment to ip address.
753 *
754 * @return bool
755 * Returns information whether the request was successful.
756 */
757 public static function removeIpFromList($id) {
758 $payload = '{"variables":{ "id": "' . $id . '" },"query":"mutation($id: ID!) { auth { sites { waf { removeFromList(id: $id) } } } }"} ';
759 $response = self::sendRequest($payload, TRUE);
760
761 if (isset($response['data']['auth']['sites']['waf']['removeFromList'])) {
762 return $response['data']['auth']['sites']['waf']['removeFromList'];
763 }
764
765 return FALSE;
766 }
767
768 /**
769 * Method to get allow url list.
770 *
771 * @param string $host_id
772 * Host id on WebTotem.
773 *
774 * @return array
775 * Returns url allow lists.
776 */
777 public static function getAllowUrlList($host_id) {
778 $payload = '{"query":"query { auth { viewer { sites { one(id: \"' . $host_id . '\"){ firewall{ urlWhiteList{ id url createdAt } } } } } } }"} ';
779 $response = self::sendRequest($payload, TRUE);
780
781 if (isset($response['data']['auth']['viewer']['sites']['one']['firewall']['urlWhiteList'])) {
782 return $response['data']['auth']['viewer']['sites']['one']['firewall']['urlWhiteList'];
783 }
784
785 return [];
786 }
787
788 /**
789 * Method to add url to allow list.
790 *
791 * @param string $host_id
792 * Host id on WebTotem.
793 * @param string $url
794 * User-specified url.
795 *
796 * @return bool|string
797 * Returns information whether the request was successful.
798 */
799 public static function addUrlToAllowList($host_id, $url) {
800 $payload = '{"variables":{ "input": { "siteId": "' . $host_id . '", "url": "' . $url . '" } }, "query":"mutation($input: WafUrlWhiteListInput!) { auth { sites { waf { addToUrlWhiteList(input: $input) } } } }"} ';
801 $response = self::sendRequest($payload, TRUE);
802
803 if (isset($response['data']['auth']['sites']['waf']['addToUrlWhiteList'])) {
804 return $response['data']['auth']['sites']['waf']['addToUrlWhiteList'];
805 }
806
807 return FALSE;
808 }
809
810 /**
811 * Method to remove url from allow list.
812 *
813 * @param string $id
814 * Id assignment to url address.
815 *
816 * @return bool|string
817 * Returns information whether the request was successful.
818 */
819 public static function removeUrlFromAllowList($id) {
820 $payload = '{"variables":{ "id": "' . $id . '" }, "query":"mutation($id: ID!) { auth { sites { waf { removeFromUrlWhiteList(id: $id) } } } }"} ';
821 $response = self::sendRequest($payload, TRUE);
822
823 if (isset($response['data']['auth']['sites']['waf']['removeFromUrlWhiteList'])) {
824 return $response['data']['auth']['sites']['waf']['removeFromUrlWhiteList'];
825 }
826
827 return FALSE;
828 }
829
830 /**
831 * Method to get user's email.
832 *
833 * @return string
834 * Returns user's email.
835 */
836 public static function getEmail(){
837 $payload = '{"query":"query { auth { viewer { email __typename } __typename } }"}';
838 $response = self::sendRequest($payload, true);
839
840 return $response['data']['auth']['viewer']['email'];
841 }
842
843 /**
844 * Function sends GraphQL request to API server.
845 *
846 * @param string $payload
847 * Payload to be sent to API server.
848 * @param bool $token
849 * Whether a token is needed when sending a request.
850 * @param bool $repeat
851 * Required to avoid recursion.
852 *
853 * @return array
854 * Returns response from WebTotem API.
855 */
856 protected static function sendRequest($payload, $token = FALSE, $repeat = FALSE) {
857
858 $api_key = WebTotemOption::getOption('api_key');
859
860 // Checking whether a token is needed.
861 if ($token) {
862 $auth_token = WebTotemOption::getOption('auth_token');
863 $auth_token_expired = WebTotemOption::getOption('auth_token_expired');
864
865 // Checking whether the token has expired.
866 if ($auth_token_expired <= time() && !$repeat) {
867 $result = self::auth($api_key);
868 if ($result === 'success') {
869 return self::sendRequest($payload, $token, TRUE);
870 }
871 else {
872 if(isset($result['errors'])){
873 $message = WebTotem::messageForHuman($result['errors'][0]['message']);
874 WebTotemOption::setNotification('error', $message);
875 }
876 }
877 }
878 }
879
880 if (function_exists('wp_remote_post')) {
881
882 $args = [
883 'body' => $payload,
884 'timeout' => '60',
885 'sslverify' => false,
886 'headers' => [
887 'Content-Type:application/json',
888 'Content-Type' => 'application/json',
889 'Accept: application/json',
890 'source: WORDPRESS',
891 ],
892 ];
893
894 if (isset($auth_token)) {
895 $auth = "Bearer " . $auth_token;
896 $args['headers'] = array_merge($args['headers'], ["Authorization" => $auth]);
897 }
898
899 $response = wp_remote_post(WEBTOTEM_API_URL, $args);
900 $response = wp_remote_retrieve_body($response);
901 $response = json_decode($response, true);
902
903 }
904 else {
905 $error = 'WP_REMOTE_POST_NOT_EXIST';
906 }
907
908 // Checking if there are errors in the response.
909 if (isset($response['errors'][0]['message'])) {
910 $message = WebTotem::messageForHuman($response['errors'][0]['message']);
911 if (stripos($response['errors'][0]['message'], "INVALID_TOKEN") !== FALSE && !$repeat) {
912 $response = self::auth($api_key);
913 if ($response === 'success') {
914 return self::sendRequest($payload, $token, TRUE);
915 }
916 }
917 else {
918 if ($message !== FALSE) {
919 WebTotemOption::setNotification('error', $message); // for debug json_encode($payload).' '.
920 }
921 }
922 }
923
924 if (!empty($error)) {
925 WebTotemOption::setNotification('error', $error);
926 }
927
928 return $response;
929 }
930
931 }
932