├── docs └── README.pdf ├── .gitignore ├── examples ├── composer │ ├── .gitignore │ ├── composer.json │ ├── README.md │ └── simple.php ├── simple.php ├── simpleToken.php ├── simpleNoSslCheck.php ├── createTrigger.php ├── filter.php ├── filterByHostIds.php ├── filterByHostGroupIds.php ├── filterByHostNames.php ├── filterByHostGroupNames1.php ├── hostlistNoSslCheck.php └── filterByHostGroupNames2.php ├── composer.json ├── CHANGELOG.md ├── LICENSE ├── README.md └── src └── ZabbixApi.php /docs/README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intellitrend/zabbixapi-php/HEAD/docs/README.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ide eclipse, phpstorm 2 | .settings 3 | .buildpath 4 | .project 5 | .idea 6 | 7 | phpdoc 8 | build 9 | -------------------------------------------------------------------------------- /examples/composer/.gitignore: -------------------------------------------------------------------------------- 1 | # ide eclipse, phpstorm 2 | .settings 3 | .buildpath 4 | .project 5 | .idea 6 | 7 | phpdoc 8 | build 9 | 10 | vendor 11 | composer.phar 12 | composer.lock 13 | -------------------------------------------------------------------------------- /examples/composer/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zabbix-api/demo", 3 | "description": "", 4 | "require": { 5 | "intellitrend/zabbixapi": "v3.3.0" 6 | }, 7 | "autoload": { 8 | "psr-4": { 9 | "IntelliTrend\\Zabbix\\": "/src" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "intellitrend/zabbixapi", 3 | "description": "Zabbix API client for PHP with session cache and SSL management", 4 | "type": "library", 5 | "require": { 6 | "php": ">=5.6", 7 | "ext-curl": "*" 8 | }, 9 | "license": "LGPL-3.0", 10 | "authors": [ 11 | { 12 | "name": "IntelliTrend", 13 | "email": "support@intellitrend.de", 14 | "homepage": "https://www.intellitrend.de" 15 | } 16 | ], 17 | "support": { 18 | "issues": "https://github.com/intellitrend/zabbixapi-php/issues", 19 | "docs": "https://github.com/intellitrend/zabbixapi-php" 20 | }, 21 | "minimum-stability": "stable", 22 | "autoload": { 23 | "psr-4": { 24 | "IntelliTrend\\Zabbix\\": "/src" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /examples/simple.php: -------------------------------------------------------------------------------- 1 | login($zabUrl, $zabUser, $zabPassword); 19 | //this is similar to: $result = $zbx->call('apiinfo.version'); 20 | $result = $zbx->getApiVersion(); 21 | print "Remote Zabbix API Version:$result\n"; 22 | // Get number of host available to this useraccount 23 | $result = $zbx->call('host.get',array("countOutput" => true)); 24 | print "Number of Hosts:$result\n"; 25 | } catch (ZabbixApiException $e) { 26 | print "==== Zabbix API Exception ===\n"; 27 | print 'Errorcode: '.$e->getCode()."\n"; 28 | print 'ErrorMessage: '.$e->getMessage()."\n"; 29 | exit; 30 | } catch (Exception $e) { 31 | print "==== Exception ===\n"; 32 | print 'Errorcode: '.$e->getCode()."\n"; 33 | print 'ErrorMessage: '.$e->getMessage()."\n"; 34 | exit; 35 | } -------------------------------------------------------------------------------- /examples/simpleToken.php: -------------------------------------------------------------------------------- 1 | loginToken($zabUrl, $zabToken); 18 | //this is similar to: $result = $zbx->call('apiinfo.version'); 19 | $result = $zbx->getApiVersion(); 20 | print "Remote Zabbix API Version:$result\n"; 21 | // Get number of host available to this useraccount 22 | $result = $zbx->call('host.get',array("countOutput" => true)); 23 | print "Number of Hosts:$result\n"; 24 | } catch (ZabbixApiException $e) { 25 | print "==== Zabbix API Exception ===\n"; 26 | print 'Errorcode: '.$e->getCode()."\n"; 27 | print 'ErrorMessage: '.$e->getMessage()."\n"; 28 | exit; 29 | } catch (Exception $e) { 30 | print "==== Exception ===\n"; 31 | print 'Errorcode: '.$e->getCode()."\n"; 32 | print 'ErrorMessage: '.$e->getMessage()."\n"; 33 | exit; 34 | } -------------------------------------------------------------------------------- /examples/simpleNoSslCheck.php: -------------------------------------------------------------------------------- 1 | false, 'sslVerifyHost' => false); 19 | $zbx->login($zabUrl, $zabUser, $zabPassword, $options); 20 | //this is similar to: $result = $zbx->call('apiinfo.version'); 21 | $result = $zbx->getApiVersion(); 22 | print "Remote Zabbix API Version:$result\n"; 23 | // Get number of host available to this useraccount 24 | $result = $zbx->call('host.get',array("countOutput" => true)); 25 | print "Number of Hosts:$result\n"; 26 | } catch (ZabbixApiException $e) { 27 | print "==== Zabbix API Exception ===\n"; 28 | print 'Errorcode: '.$e->getCode()."\n"; 29 | print 'ErrorMessage: '.$e->getMessage()."\n"; 30 | exit; 31 | } catch (Exception $e) { 32 | print "==== Exception ===\n"; 33 | print 'Errorcode: '.$e->getCode()."\n"; 34 | print 'ErrorMessage: '.$e->getMessage()."\n"; 35 | exit; 36 | } -------------------------------------------------------------------------------- /examples/composer/README.md: -------------------------------------------------------------------------------- 1 | # Example using composer 2 | 3 | The package `intellitrend/zabbixapi` requires composer 2+. 4 | 5 | The following examples assumes `composer.phar` to be in the root of the project directory. Your call to composer might be different. 6 | 7 | You can download the latest version of composer [here](https://getcomposer.org/download/). 8 | 9 | ## Pepare the project that should use the package 10 | 11 | Create a `composer.json` for the project: 12 | 13 | ```json 14 | { 15 | "name": "zabbix-api/demo", 16 | "description": "", 17 | "require": { 18 | "intellitrend/zabbixapi": "v3.3.0" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "IntelliTrend\\Zabbix\\": "/src" 23 | } 24 | } 25 | } 26 | ``` 27 | 28 | ## Run composer 29 | 30 | Run `php .\composer.phar create-project` (requires composer.phar) 31 | 32 | After a successful run, the directory structure looks like this. Composer added the vendor directory and also its own created autoload files: 33 | 34 | ```text 35 | ├───projectfolder 36 | │ └───vendor 37 | │ ├───composer 38 | │ └───intellitrend 39 | │ └───zabbixapi 40 | │ ├───docs 41 | │ ├───examples 42 | │ └───src 43 | ``` 44 | 45 | Note: You can remove the `vendor` directory any time. However then you must run `php .\composer.phar create-project` again. For more composer options see the [documentation](https://getcomposer.org/doc/). 46 | 47 | ## Add the following lines to your application 48 | 49 | ```php 50 | login($zabUrl, $zabUser, $zabPassword); 19 | 20 | // this is similar to: $result = $zbx->call('apiinfo.version'); 21 | $result = $zbx->getApiVersion(); 22 | print "Remote Zabbix API Version:$result\n"; 23 | 24 | print "====================================================================\n"; 25 | 26 | // create a trigger on host 'Zabbix Server' that fires if the item 'system.cpu.util' is greater than 75 27 | $result = $zbx->call('trigger.create', array( 28 | "priority" => "3", // average 29 | "description" => "High CPU usage on {HOST.NAME}", 30 | "expression" => "last(/Zabbix server/system.cpu.util)>75", // Zabbix 5.4 and after 31 | // "expression" => "{Zabbix server:system.cpu.util.last()}>75", // before Zabbix 5.4 32 | )); 33 | 34 | // print ID of the trigger that was created 35 | print_r($result); 36 | } catch (ZabbixApiException $e) { 37 | print "==== Zabbix API Exception ===\n"; 38 | print 'Errorcode: '.$e->getCode()."\n"; 39 | print 'ErrorMessage: '.$e->getMessage()."\n"; 40 | exit; 41 | } catch (Exception $e) { 42 | print "==== Exception ===\n"; 43 | print 'Errorcode: '.$e->getCode()."\n"; 44 | print 'ErrorMessage: '.$e->getMessage()."\n"; 45 | exit; 46 | } 47 | ?> 48 | -------------------------------------------------------------------------------- /examples/composer/simple.php: -------------------------------------------------------------------------------- 1 | setDebug(true); 23 | // default is to verify certificate and hostname 24 | $zbx->login($zabUrl, $zabUser, $zabPassword); 25 | // loginToken() accepts API tokens as an alternative to login() 26 | // $zbx->loginToken($zabUrl, $zabToken); 27 | // this is similar to: $result = $zbx->call('apiinfo.version'); 28 | $result = $zbx->getApiVersion(); 29 | print "Remote Zabbix API Version:$result\n"; 30 | // get number of host available to this useraccount 31 | $result = $zbx->call('host.get',array("countOutput" => true)); 32 | print "Number of Hosts:$result\n"; 33 | // calling logout will logout from zabbix (deleteing the session) and also delete the local session cache 34 | // if your application is called periodically, the do not logout to benefit from session cache 35 | // $zbx->logout(); 36 | } catch (ZabbixApiException $e) { 37 | print "==== Zabbix API Exception ===\n"; 38 | print 'Errorcode: '.$e->getCode()."\n"; 39 | print 'ErrorMessage: '.$e->getMessage()."\n"; 40 | exit; 41 | } catch (Exception $e) { 42 | print "==== Exception ===\n"; 43 | print 'Errorcode: '.$e->getCode()."\n"; 44 | print 'ErrorMessage: '.$e->getMessage()."\n"; 45 | exit; 46 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 3.3.0 4 | 5 | * Added support for Zabbix 7.2. 6 | * Fixed `connectTimeout` setting the regular timeout instead of the connection timeout. 7 | 8 | ## Version 3.2.0 9 | 10 | * Added custom exception class ZabbixApiException. 11 | * Fixed exception handling issues in function `call()` if other exceptions are thrown by custom handlers. 12 | 13 | ## Version 3.1.0 14 | 15 | * Tested with Zabbix 6.0. 16 | * Added missing namespace in examples. 17 | * Added function `loginToken()` to log in via API tokens. 18 | 19 | ## Version 3.0.2 20 | 21 | * Fixed bug in getApiVersion() with invalid credentials. 22 | * Added example and documentation using composer. See `examples/composer`. 23 | 24 | ## Version 3.0.1 25 | 26 | * Tested with Zabbix 5.0 - 5.4. 27 | * Added support for Zabbix 5.4 API change in `user.login` method. 28 | * Added namespace `IntelliTrend\Zabbix`. 29 | * Added [composer](https://getcomposer.org/) support. 30 | * Moved to [semver](https://semver.org/) version numbers. 31 | 32 | ## No version change 33 | 34 | * Added more examples to filter by hostnames, hostids, hostgroupnames and hostgroupids. 35 | 36 | ## Version 2.8 37 | 38 | * Tested with Zabbix 5.0 and 5.2. 39 | * Ensure that params passed to API call are an array. 40 | * Added library version to debug output. 41 | 42 | ## Version 2.7 43 | 44 | * BREAKING CHANGE: Classfilename renamed from `Zabbixapi.php` to `ZabbixApi.php` to match classname. 45 | * Call to `getAuthKey()` no longer simply returns the `authKey`. If there was no previous call to the Zabbix-API this funcion will call the Zabbix-API to ensure a valid key before returning the key. 46 | * Fixed error message for invalid sslCaFile. 47 | 48 | ## Version 2.6 49 | 50 | * Public release. 51 | * Added check for Curl. 52 | * Added example for filtering and additional params passed to the Zabbix-API. 53 | * Call to `login()` no longer initially calls the Zabbix-API anylonger to verify the `authKey`. 54 | * If debug is enabled via option, or via function before calling `login()`, `login()` issues a call to the Zabbix-API to check wether the session is re-used. 55 | 56 | ## Version 2.5 57 | 58 | * Internal release. 59 | 60 | ## Version 2.4 61 | 62 | * Initial public release. -------------------------------------------------------------------------------- /examples/filter.php: -------------------------------------------------------------------------------- 1 | login($zabUrl, $zabUser, $zabPassword); 19 | 20 | //this is similar to: $result = $zbx->call('apiinfo.version'); 21 | $result = $zbx->getApiVersion(); 22 | print "Remote Zabbix API Version:$result\n"; 23 | 24 | print "====================================================================\n"; 25 | // Get hosts and other information available to this useraccount, but filtered and limited 26 | $limit = 5; 27 | $params = array( 28 | 'output' => array('hostid', 'host', 'name', 'status', 'maintenance_status', 'description'), 29 | 'filter' => array('status' => 0, 'maintenance_status' => 0, 'type' => 1), 30 | 'selectGroups' => array('groupid', 'name'), 31 | 'selectInterfaces' => array('interfaceid', 'main', 'type', 'useip', 'ip', 'dns', 'port'), 32 | 'selectInventory' => array('os', 'contact', 'location'), 33 | 'selectMacros' => array('macro', 'value'), 34 | 'limit' => $limit 35 | ); 36 | 37 | $result = $zbx->call('host.get',$params); 38 | print "==== Filtered hostlist with groups and macros ====\n"; 39 | foreach($result as $host) { 40 | printf("HostId:%d - Host:%s\n", $host['hostid'], $host['host']); 41 | foreach($host['groups'] as $group) { 42 | printf(" - GroupId:%d - Group:%s\n", $group['groupid'], $group['name']); 43 | } 44 | foreach($host['macros'] as $macro) { 45 | printf(" - Macro:%s - Value:%s\n", $macro['macro'], $macro['value']); 46 | } 47 | 48 | } 49 | } catch (ZabbixApiException $e) { 50 | print "==== Zabbix API Exception ===\n"; 51 | print 'Errorcode: '.$e->getCode()."\n"; 52 | print 'ErrorMessage: '.$e->getMessage()."\n"; 53 | exit; 54 | } catch (Exception $e) { 55 | print "==== Exception ===\n"; 56 | print 'Errorcode: '.$e->getCode()."\n"; 57 | print 'ErrorMessage: '.$e->getMessage()."\n"; 58 | exit; 59 | } -------------------------------------------------------------------------------- /examples/filterByHostIds.php: -------------------------------------------------------------------------------- 1 | login($zabUrl, $zabUser, $zabPassword); 19 | 20 | // this is similar to: $result = $zbx->call('apiinfo.version'); 21 | $result = $zbx->getApiVersion(); 22 | print "Remote Zabbix API Version:$result\n"; 23 | 24 | print "====================================================================\n"; 25 | // get hosts and other information available to this useraccount, but filtered by hostids 26 | // note: [] is a more modern way of array() 27 | $hostIds = [10126, 10127]; 28 | 29 | $params = array( 30 | 'output' => array('hostid', 'host', 'name', 'status', 'maintenance_status', 'description'), 31 | 'hostids' => $hostIds, 32 | 'selectGroups' => array('groupid', 'name'), 33 | 'selectInterfaces' => array('interfaceid', 'main', 'type', 'useip', 'ip', 'dns', 'port'), 34 | 'selectInventory' => array('os', 'contact', 'location'), 35 | 'selectMacros' => array('macro', 'value') 36 | ); 37 | 38 | $result = $zbx->call('host.get',$params); 39 | print "==== Filtered hostlist with groups and macros ====\n"; 40 | foreach($result as $host) { 41 | printf("HostId:%d - Host:%s - Name:%s\n", $host['hostid'], $host['host'], $host['name']); 42 | foreach($host['groups'] as $group) { 43 | printf(" - GroupId:%d - Group:%s\n", $group['groupid'], $group['name']); 44 | } 45 | foreach($host['macros'] as $macro) { 46 | printf(" - Macro:%s - Value:%s\n", $macro['macro'], $macro['value']); 47 | } 48 | 49 | } 50 | } catch (ZabbixApiException $e) { 51 | print "==== Zabbix API Exception ===\n"; 52 | print 'Errorcode: '.$e->getCode()."\n"; 53 | print 'ErrorMessage: '.$e->getMessage()."\n"; 54 | exit; 55 | } catch (Exception $e) { 56 | print "==== Exception ===\n"; 57 | print 'Errorcode: '.$e->getCode()."\n"; 58 | print 'ErrorMessage: '.$e->getMessage()."\n"; 59 | exit; 60 | } -------------------------------------------------------------------------------- /examples/filterByHostGroupIds.php: -------------------------------------------------------------------------------- 1 | login($zabUrl, $zabUser, $zabPassword); 19 | 20 | //this is similar to: $result = $zbx->call('apiinfo.version'); 21 | $result = $zbx->getApiVersion(); 22 | print "Remote Zabbix API Version:$result\n"; 23 | 24 | print "====================================================================\n"; 25 | // get hosts and other information available to this useraccount, but filtered by hostGroupIds 26 | // note: [] is a more modern way of array() 27 | $hostGroupIds = [4, 12]; 28 | 29 | $params = array( 30 | 'output' => array('hostid', 'host', 'name', 'status', 'maintenance_status', 'description'), 31 | 'groupids' => $hostGroupIds, 32 | 'selectGroups' => array('groupid', 'name'), 33 | 'selectInterfaces' => array('interfaceid', 'main', 'type', 'useip', 'ip', 'dns', 'port'), 34 | 'selectInventory' => array('os', 'contact', 'location'), 35 | 'selectMacros' => array('macro', 'value') 36 | ); 37 | 38 | $result = $zbx->call('host.get',$params); 39 | print "==== Filtered hostlist with groups and macros ====\n"; 40 | foreach($result as $host) { 41 | printf("HostId:%d - Host:%s - Name:%s\n", $host['hostid'], $host['host'], $host['name']); 42 | foreach($host['groups'] as $group) { 43 | printf(" - GroupId:%d - Group:%s\n", $group['groupid'], $group['name']); 44 | } 45 | foreach($host['macros'] as $macro) { 46 | printf(" - Macro:%s - Value:%s\n", $macro['macro'], $macro['value']); 47 | } 48 | 49 | } 50 | } catch (ZabbixApiException $e) { 51 | print "==== Zabbix API Exception ===\n"; 52 | print 'Errorcode: '.$e->getCode()."\n"; 53 | print 'ErrorMessage: '.$e->getMessage()."\n"; 54 | exit; 55 | } catch (Exception $e) { 56 | print "==== Exception ===\n"; 57 | print 'Errorcode: '.$e->getCode()."\n"; 58 | print 'ErrorMessage: '.$e->getMessage()."\n"; 59 | exit; 60 | } -------------------------------------------------------------------------------- /examples/filterByHostNames.php: -------------------------------------------------------------------------------- 1 | login($zabUrl, $zabUser, $zabPassword); 19 | 20 | // this is similar to: $result = $zbx->call('apiinfo.version'); 21 | $result = $zbx->getApiVersion(); 22 | print "Remote Zabbix API Version:$result\n"; 23 | 24 | print "====================================================================\n"; 25 | // get hosts and other information available to this useraccount, but filtered by hostnames 26 | // note: [] is a more modern way of array() 27 | $hostNames = ['Zabbix Server', 'Test Server']; 28 | 29 | $params = array( 30 | 'output' => array('hostid', 'host', 'name', 'status', 'maintenance_status', 'description'), 31 | 'filter' => array('host' => $hostNames), 32 | 'selectGroups' => array('groupid', 'name'), 33 | 'selectInterfaces' => array('interfaceid', 'main', 'type', 'useip', 'ip', 'dns', 'port'), 34 | 'selectInventory' => array('os', 'contact', 'location'), 35 | 'selectMacros' => array('macro', 'value') 36 | ); 37 | 38 | $result = $zbx->call('host.get',$params); 39 | print "==== Filtered hostlist with groups and macros ====\n"; 40 | foreach($result as $host) { 41 | printf("HostId:%d - Host:%s - Name:%s\n", $host['hostid'], $host['host'], $host['name']); 42 | foreach($host['groups'] as $group) { 43 | printf(" - GroupId:%d - Group:%s\n", $group['groupid'], $group['name']); 44 | } 45 | foreach($host['macros'] as $macro) { 46 | printf(" - Macro:%s - Value:%s\n", $macro['macro'], $macro['value']); 47 | } 48 | 49 | } 50 | } catch (ZabbixApiException $e) { 51 | print "==== Zabbix API Exception ===\n"; 52 | print 'Errorcode: '.$e->getCode()."\n"; 53 | print 'ErrorMessage: '.$e->getMessage()."\n"; 54 | exit; 55 | } catch (Exception $e) { 56 | print "==== Exception ===\n"; 57 | print 'Errorcode: '.$e->getCode()."\n"; 58 | print 'ErrorMessage: '.$e->getMessage()."\n"; 59 | exit; 60 | } -------------------------------------------------------------------------------- /examples/filterByHostGroupNames1.php: -------------------------------------------------------------------------------- 1 | login($zabUrl, $zabUser, $zabPassword); 19 | 20 | // this is similar to: $result = $zbx->call('apiinfo.version'); 21 | $result = $zbx->getApiVersion(); 22 | print "Remote Zabbix API Version:$result\n"; 23 | 24 | print "====================================================================\n"; 25 | // get hostGroups and attach hosts available to this useraccount, filtered by hostGroupNames 26 | // note: [] is a more modern way of array() 27 | // depending how much details about the host is needed, 2 options are available: 28 | // 1. 1 call: Get hostGroups and add corresponding hosts to the result 29 | // 2. 2 Calls: Get hostGroupIds based on theirs names, then get hosts with detailed info 30 | 31 | // here we use method 1 - 1 call 32 | // get hostGroupIds by name and add hosts to result 33 | $hostGroupNames = ['Zabbix servers', 'IntelliTrend/Development']; 34 | 35 | $params = array( 36 | 'output' => array('groupid', 'name'), 37 | 'filter' => array('name' => $hostGroupNames), 38 | 'selectHosts' => array('hostid', 'host', 'name', 'status', 'maintenance_status', 'description') 39 | ); 40 | 41 | $result = $zbx->call('hostgroup.get',$params); 42 | print "==== Hosts filtered by hostGroups - one call ====\n"; 43 | foreach($result as $hostGroup) { 44 | printf("GroupId:%d - Group:%s\n", $hostGroup['groupid'], $hostGroup['name']); 45 | foreach($hostGroup['hosts'] as $host) { 46 | printf(" - HostId:%d - Host:%s - Name:%s\n", $host['hostid'], $host['host'], $host['name']); 47 | } 48 | } 49 | } catch (ZabbixApiException $e) { 50 | print "==== Zabbix API Exception ===\n"; 51 | print 'Errorcode: '.$e->getCode()."\n"; 52 | print 'ErrorMessage: '.$e->getMessage()."\n"; 53 | exit; 54 | } catch (Exception $e) { 55 | print "==== Exception ===\n"; 56 | print 'Errorcode: '.$e->getCode()."\n"; 57 | print 'ErrorMessage: '.$e->getMessage()."\n"; 58 | exit; 59 | } -------------------------------------------------------------------------------- /examples/hostlistNoSslCheck.php: -------------------------------------------------------------------------------- 1 | getVersion(). "\n"; 19 | try { 20 | // disable validation off certificate and host 21 | $options = array('sslVerifyPeer' => false, 'sslVerifyHost' => false); 22 | $zbx->login($zabUrl, $zabUser, $zabPassword, $options); 23 | 24 | //this is similar to: $result = $zbx->call('apiinfo.version'); 25 | $result = $zbx->getApiVersion(); 26 | print "Remote Zabbix API Version:$result\n"; 27 | 28 | print "Debugging set to on\n"; 29 | $zbx->setDebug(true); 30 | 31 | // Get host count 32 | $params = array( 33 | // count of hosts - no ids, no details 34 | "countOutput" => true 35 | ); 36 | $result = $zbx->call('host.get',$params); 37 | print "Number of Hosts:$result\n"; 38 | 39 | print "Debugging set to off\n"; 40 | $zbx->setDebug(false); 41 | 42 | $limit = 5; 43 | $params = array( 44 | // limit host info to these fields, to get all use "extend" instead of field list 45 | "output" => array("hostid", "host", "name", "status"), 46 | // limit number of hosts returned, otherwise get all hosts you have access to 47 | "limit" => $limit 48 | ); 49 | $result = $zbx->call('host.get',$params); 50 | 51 | 52 | print "Getting hostlist - limited to:$limit\n"; 53 | foreach ($result as $v) { 54 | $hostid = $v['hostid']; 55 | $hostname = $v['host']; 56 | $name = $v['name']; 57 | $status = $v['status']; 58 | print "hostid:$hostid, status:$status, hostname:$hostname, alias:$name\n"; 59 | } 60 | 61 | // logout() would logout from api and also delete the session file locally 62 | //$zbx->logout(); 63 | } catch (ZabbixApiException $e) { 64 | print "==== Zabbix API Exception ===\n"; 65 | print 'Errorcode: '.$e->getCode()."\n"; 66 | print 'ErrorMessage: '.$e->getMessage()."\n"; 67 | exit; 68 | } catch (Exception $e) { 69 | print "==== Exception ===\n"; 70 | print 'Errorcode: '.$e->getCode()."\n"; 71 | print 'ErrorMessage: '.$e->getMessage()."\n"; 72 | exit; 73 | } -------------------------------------------------------------------------------- /examples/filterByHostGroupNames2.php: -------------------------------------------------------------------------------- 1 | login($zabUrl, $zabUser, $zabPassword); 19 | 20 | // this is similar to: $result = $zbx->call('apiinfo.version'); 21 | $result = $zbx->getApiVersion(); 22 | print "Remote Zabbix API Version:$result\n"; 23 | 24 | print "====================================================================\n"; 25 | // get hostGroups and attach hosts available to this useraccount, filtered by hostGroupNames 26 | // note: [] is a more modern way of array() 27 | // depending how much details about the host is needed, 2 options are available: 28 | // 1. 1 call: Get hostGroups and add corresponding hosts to the result 29 | // 2. 2 calls: Get hostGroupIds based on theirs names, then get hosts with detailed info 30 | 31 | // here we use method 2 - 2 calls 32 | // note: if a host belongs to other groups as filtered in the 1st call 33 | // these goups are also listed in the 2nd call. 34 | // get hostGroupIds by name and then execute a 2nd call to get the hosts with additional data 35 | $hostGroupNames = ['Zabbix servers', 'IntelliTrend/Development']; 36 | 37 | $params = array( 38 | 'output' => array('groupid', 'name'), 39 | 'filter' => array('name' => $hostGroupNames), 40 | ); 41 | 42 | $result = $zbx->call('hostgroup.get',$params); 43 | print "==== Hosts filtered by hostGroups - 2 calls ====\n"; 44 | print "==== 1. Call: Filtered hostGroups ====\n"; 45 | // save the ids for next call 46 | $hostGroupIds = []; 47 | foreach($result as $hostGroup) { 48 | printf("GroupId:%d - Group:%s\n", $hostGroup['groupid'], $hostGroup['name']); 49 | $hostGroupIds[] = $hostGroup['groupid']; 50 | } 51 | 52 | // get hosts based on the hostGroupIds 53 | $params = array( 54 | 'output' => array('hostid', 'host', 'name', 'status', 'maintenance_status', 'description'), 55 | 'groupids' => $hostGroupIds, 56 | 'selectGroups' => array('groupid', 'name'), 57 | 'selectInterfaces' => array('interfaceid', 'main', 'type', 'useip', 'ip', 'dns', 'port'), 58 | 'selectInventory' => array('os', 'contact', 'location'), 59 | 'selectMacros' => array('macro', 'value') 60 | ); 61 | 62 | $result = $zbx->call('host.get',$params); 63 | print "==== 2. Call: Filtered hostlist with groups and macros ====\n"; 64 | foreach($result as $host) { 65 | printf("HostId:%d - Host:%s - Name:%s\n", $host['hostid'], $host['host'], $host['name']); 66 | foreach($host['groups'] as $group) { 67 | printf(" - GroupId:%d - Group:%s\n", $group['groupid'], $group['name']); 68 | } 69 | foreach($host['macros'] as $macro) { 70 | if (!isset($macro['value'])) { 71 | $macro['value'] = ''; 72 | } 73 | printf(" - Macro:%s - Value:%s\n", $macro['macro'], $macro['value']); 74 | } 75 | 76 | } 77 | } catch (ZabbixApiException $e) { 78 | print "==== Zabbix API Exception ===\n"; 79 | print 'Errorcode: '.$e->getCode()."\n"; 80 | print 'ErrorMessage: '.$e->getMessage()."\n"; 81 | exit; 82 | } catch (Exception $e) { 83 | print "==== Exception ===\n"; 84 | print 'Errorcode: '.$e->getCode()."\n"; 85 | print 'ErrorMessage: '.$e->getMessage()."\n"; 86 | exit; 87 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | This software is licensed under the GNU Lesser General Public License v3.0. 4 | 5 | # Changelog 6 | 7 | See [CHANGELOG.md](/CHANGELOG.md). 8 | 9 | # Zabbix API PHP Client with session caching and SSL support 10 | 11 | There are quite a lot of Zabbix API clients out that work really well with [Zabbix](https://www.zabbix.com). However most of them do not support `session caching` or need tweaks to work with self signed certificates. 12 | 13 | This library aims to solve those problems. It supports the following features: 14 | 15 | * Session caching. 16 | * HTTPS connections with official- and self-signed certificates. 17 | * Works with Linux and Windows PHP implementations. 18 | * Multiple concurrent connections with different user accounts and/or different servers. 19 | * Zabbix versions: 3.0 up to 7.2 20 | * No installation required. 21 | 22 | It is commercially backed up and maintained by [IntelliTrend GmbH](https://www.intellitrend.de), an official Zabbix Partner and Zabbix Training company. 23 | 24 | There was also a lightning talk [Zabbix API – the easy way](https://blog.zabbix.com/zabbix-api-the-easy-way/11748/) about using this library on the Zabbix conference 2020 in Benelux. 25 | 26 | ## Why Session caching? 27 | 28 | ### How authentication via API usally works 29 | 30 | Each time an application uses `user.login`, the Zabbix API creates a so called `AuthKey`. (See [user.login](https://www.zabbix.com/documentation/5.0/manual/api/reference/user/login)). This key is then passed via each request through the `auth` request property. 31 | 32 | In most cases, the API libary does this transparently for the user. However, if the script is called later on again (i.e by a cron job), a new `user.login` is performed, thus creating a new `AuthKey` for that new session. 33 | 34 | Zabbix keeps those session, until a session expired or is logged out. You can check your actual settings through the Zabbix frontend: `Administration/General/Housekeeper - Section Sessions`. The default value is 365days. 35 | 36 | This means, any created session (if there is no logout) will be kept for 365 days. 37 | 38 | Assume we have a set of 10 API scripts that run every hour. This means we will create `10 x 24 = 240` sessions per day. Using more scripts or a smaller interval will of cause increase this number. 39 | 40 | **Note**: Zabbix 5.4 and later support API auth tokens, which won't create sessions when used. Therefore, no session management is required on the client side, either. 41 | 42 | ### The problem with many sessions in the session table 43 | 44 | Everytime a request hits the Zabbix frontend, either per webbrowser or as a JSON RPC API request, Zabbix has to verify the request against the existing sessions. The more sessions to verify, the longer this will take. 45 | 46 | > **Note:** We have seen installations with millions of sessions, where frontend access slowed down considerable by 15sec+ per request. Keep in mind that for example the dashboard not only performs one request, but multiple requests depending on the number of widgets used. 47 | 48 | So the best is to `reuse` a session, until it expires. This is where session caching steps in. 49 | 50 | ## Using session caching with the Zabbix API 51 | 52 | When a new session is created, the AuthKey is saved encrypted to disk. This is similar to using a cookie in a classic webbrowser. If a new request is performed, the existing session is read once and the AuthKey is reused. 53 | 54 | So to follow up the example given before: Calling a script using session-caching, even over a month, will create just `1` session. 55 | 56 | If the AuthKey becomes invalid, the libary automatically performs a new `user.login`, re-executes the failed request and updates the stored session. All of this happens in the background, the user of the libary has not to deal with it. 57 | 58 | ### How does session encryption work, what about multiple sessions? 59 | 60 | Each session has a unique name based on a hash using the `zabbixUserName` and the `zabbixUrl`. 61 | The session itself is encrypted using the `zabbixUserName` and the `zabbixPassword`. 62 | 63 | This way, the libary can be used with different useraccounts and also different zabbix server instances. 64 | 65 | ### Where are sessions stored? 66 | 67 | Sessions are stored by default in the users `tmp` directory. However there is a config option `sessionDir` that allows to override this setting. See the detailed description below. 68 | 69 | # Installation 70 | 71 | > **Note:** The PHP environment **must have CURL** installed. `ZabbixApi.php` has a built-in check for curl and will throw an exception if curl is missing. 72 | 73 | ## Without using composer 74 | 75 | There is no installation required. Simply copy the file `ZabbixApi.php` and use the class. 76 | 77 | ```php 78 | require_once "ZabbixApi.php"; 79 | 80 | use IntelliTrend\Zabbix\ZabbixApi; 81 | 82 | $zbx = new ZabbixApi(); 83 | ``` 84 | 85 | ## Using composer 86 | 87 | ```php 88 | require('vendor/autoload.php'); 89 | 90 | use IntelliTrend\Zabbix\ZabbixApi; 91 | 92 | $zbx = new ZabbixApi(); 93 | ``` 94 | 95 | See `examples/composer` for a full example with details. 96 | 97 | # Usage 98 | 99 | ## Error handling 100 | 101 | The library makes use of `Exceptions`. There is no need to check each response value. Simply wrap the calls in `try/catch blocks`. 102 | 103 | Depending on where an error occurs, different error codes are passed to the exception object, together with the message property. 104 | 105 | * `Zabbix API errors`: The original API error code and message is passed. 106 | * `Connection and SSL errors`: The original CURL error code and message is passed. 107 | * `Library errors`: A constant error code, as defined in the class constant EXCEPTION_CLASS_CODE, and a useful message is passed. Default=1000. 108 | 109 | ## Configuration 110 | 111 | The class is configured when calling the `login` method. Any further Zabbix API call is performed by the `call` method. 112 | 113 | > **Note:** One can run multiple instances at the same time, connecting with different user accounts to the same zabbix server or to another zabbix server. 114 | 115 | ## Basic usage 116 | 117 | Lets start with a very simple example: 118 | 119 | ```php 120 | require_once "ZabbixApi.php"; 121 | use IntelliTrend\Zabbix\ZabbixApi; 122 | $zbx = new ZabbixApi(); 123 | try { 124 | $zbx->login('https://my.zabbixurl.com/zabbix', 'myusername', 'mypassword'); 125 | $result = $zbx->call('host.get', array("countOutput" => true)); 126 | print "Number of hosts:$result\n"; 127 | } catch (Exception $e) { 128 | print "==== Exception ===\n"; 129 | print 'Errorcode: '.$e->getCode()."\n"; 130 | print 'ErrorMessage: '.$e->getMessage()."\n"; 131 | exit; 132 | } 133 | ``` 134 | 135 | Basically this is all needed. The `call` method is transparent to the Zabbix API definition. It takes 2 parameter: `$method` and `$params` as specified for the particular Zabbix API method. 136 | 137 | Instead of a login with a user name and password, you can also use an API token in Zabbix 5.4+: 138 | 139 | ```php 140 | require_once "ZabbixApi.php"; 141 | use IntelliTrend\Zabbix\ZabbixApi; 142 | $zbx = new ZabbixApi(); 143 | try { 144 | $zbx->loginToken('https://my.zabbixurl.com/zabbix', '123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234'); 145 | $result = $zbx->call('host.get', array("countOutput" => true)); 146 | print "Number of hosts:$result\n"; 147 | } catch (Exception $e) { 148 | print "==== Exception ===\n"; 149 | print 'Errorcode: '.$e->getCode()."\n"; 150 | print 'ErrorMessage: '.$e->getMessage()."\n"; 151 | exit; 152 | } 153 | ``` 154 | 155 | For example to retrieve all 'Host Groups' with all properties, we can do this: 156 | 157 | ```php 158 | require_once "ZabbixApi.php"; 159 | use IntelliTrend\Zabbix\ZabbixApi; 160 | $zbx = new ZabbixApi(); 161 | $zabUrl = 'https://my.zabbixurl.com/zabbix'; 162 | $zabUser = 'myusername'; 163 | $zabPassword = 'mypassword'; 164 | try { 165 | $zbx->login($zabUrl, $zabUser, $zabPassword); 166 | $result = $zbx->call('hostgroup.get', array("output" => 'extend')); 167 | foreach ($result as $hostGroup) { 168 | $hostGroupId = $hostGroup['groupid']; 169 | $hostGroupName = $hostGroup['name']; 170 | print "groupid:$hostGroupId, hostGroupName:$hostGroupName\n"; 171 | } 172 | } catch (Exception $e) { 173 | print "==== Exception ===\n"; 174 | print 'Errorcode: '.$e->getCode()."\n"; 175 | print 'ErrorMessage: '.$e->getMessage()."\n"; 176 | exit; 177 | } 178 | ``` 179 | 180 | > **Note:** This second example would not create a new session when calling `login` again after the first example. It would reuse the session from the previous example. `login` returns true when an existing session was found. 181 | 182 | ## Advanced usage and SSL Options 183 | 184 | The basic example works fine, even with HTTPS, given there is a valid certificate the php installation is aware of. But what todo when using self-signed certificates? 185 | 186 | Here we can use the optional `options` argument when calling `login` to setup the SSL options. 187 | 188 | Example - Turn off SSL verification: 189 | 190 | ```php 191 | require_once "ZabbixApi.php"; 192 | use IntelliTrend\Zabbix\ZabbixApi; 193 | $zbx = new ZabbixApi(); 194 | $options = array('sslVerifyPeer' => false, 'sslVerifyHost' => false); 195 | try { 196 | $zbx->login('https://my.zabbixurl.com/zabbix', 'myusername', 'mypassword', $options); 197 | $result = $zbx->call('host.get', array("countOutput" => true)); 198 | print "Number of hosts:$result\n"; 199 | } catch (Exception $e) { 200 | print "==== Exception ===\n"; 201 | print 'Errorcode: '.$e->getCode()."\n"; 202 | print 'ErrorMessage: '.$e->getMessage()."\n"; 203 | exit; 204 | } 205 | ``` 206 | 207 | ## Using filters and field selectors 208 | 209 | It is quite easy to pass filter and field selectors through the API. Basically any params defined by the Zabbix-API can be passed this way. 210 | 211 | Example - Select first 5 hosts filtered by status, maintenance_status and type and add their groups and macros. 212 | 213 | ```php 214 | require_once "ZabbixApi.php"; 215 | use IntelliTrend\Zabbix\ZabbixApi; 216 | $zbx = new ZabbixApi(); 217 | try { 218 | // default is to verify certificate and hostname 219 | $options = array('sslVerifyPeer' => false, 'sslVerifyHost' => false); 220 | $zbx->login('https://my.zabbixurl.com/zabbix', 'myusername', 'mypassword', $options); 221 | 222 | print "====================================================================\n"; 223 | // Get hosts and other information available to this useraccount, but filtered and limited 224 | $limit = 5; 225 | $params = array( 226 | 'output' => array('hostid', 'host', 'name', 'status', 'maintenance_status', 'description'), 227 | 'filter' => array('status' => 0, 'maintenance_status' => 0, 'type' => 1), 228 | 'selectGroups' => array('groupid', 'name'), 229 | 'selectInterfaces' => array('interfaceid', 'main', 'type', 'useip', 'ip', 'dns', 'port'), 230 | 'selectInventory' => array('os', 'contact', 'location'), 231 | 'selectMacros' => array('macro', 'value'), 232 | 'limit' => $limit 233 | ); 234 | 235 | $result = $zbx->call('host.get',$params); 236 | print "==== Filtered hostlist with groups and macros ====\n"; 237 | foreach($result as $host) { 238 | printf("HostId:%d - Host:%s\n", $host['hostid'], $host['host']); 239 | foreach($host['groups'] as $group) { 240 | printf(" - GroupId:%d - Group:%s\n", $group['groupid'], $group['name']); 241 | } 242 | foreach($host['macros'] as $macro) { 243 | printf(" - Macro:%s - Value:%s\n", $macro['macro'], $macro['value']); 244 | } 245 | 246 | } 247 | 248 | } catch (Exception $e) { 249 | print "==== Exception ===\n"; 250 | print 'Errorcode: '.$e->getCode()."\n"; 251 | print 'ErrorMessage: '.$e->getMessage()."\n"; 252 | exit; 253 | } 254 | ``` 255 | 256 | ## Debug Mode 257 | 258 | The class provides a debug mode that ouputs a lot of details. To enable, either use an option or function. 259 | 260 | Debug Option as param in login(): 261 | 262 | ```php 263 | $zbx = new ZabbixApi(); 264 | try { 265 | $options = array('sslVerifyPeer' => false, 'sslVerifyHost' => false, 'debug' => true); 266 | $zbx->login('https://my.zabbixurl.com/zabbix', 'myusername', 'mypassword', $options); 267 | ... 268 | ``` 269 | 270 | Debug Function - can be used any time: 271 | 272 | ```php 273 | # Turn debug on 274 | $zbx = new ZabbixApi(); 275 | $zbx->setDebug(true); 276 | try { 277 | $options = array('sslVerifyPeer' => false, 'sslVerifyHost' => false); 278 | $zbx->login('https://my.zabbixurl.com/zabbix', 'myusername', 'mypassword', $options); 279 | ... 280 | # Can be turned off anytime 281 | $zbx->setDebug(false); 282 | ... 283 | # And turned on again 284 | $zbx->setDebug(true); 285 | ``` 286 | 287 | # Functions reference 288 | 289 | ## Basic functions 290 | 291 | ### login($zabUrl, $zabUser, $zabPassword, $options) 292 | 293 | Initial login. Configures the class and loads a cached session if it exists. It does not executes a request to the remote server to test the credentials or session at this time. This happens automatically during the first call to the Zabbix-API. One can enforce the validation by calling `getAuthKey()` after `login()`. 294 | 295 | > **Note:** If debug is enabled via option, or via function before calling `login()`, `login()` issues a call to the Zabbix-API to check wether the session is re-used. 296 | 297 | * `return` void 298 | * `throws` ZabbixApiException. Invalid options, session issues or connection problems. 299 | * `param` string $zabUrl 300 | * `param` string $zabUser 301 | * `param` string $zabPassword 302 | * `param` array $options - optional settings. 303 | Example: `array('sslVerifyPeer' => false, 'sslVerifyHost' => false);` 304 | * `debug`: boolean - default=false. Show debug information. Also setDebug() can be used. Default is false 305 | * `sessionDir`: string - default=user `tmp` directory. Directory where to store the sessions. 306 | * `sslCaFile`: string - default=use php.ini settings. Filename of external CACertBundle. Useful when using self signed certificates from internal CA. See the CURL or Mozilla websites for those bundles. 307 | * `sslVerifyPeer`: boolean - default=true. Verify certificate. Throws Exception on failure. When false, ignore any verfication errors. 308 | * `sslVerifyHost`: boolean - default=true. Verify Hostname against CN in certificate. Only works if certificate can be validated. 309 | 310 | > **Note:** If sslVerifyPeer=false but the certificate itself is valid and the hostname does not match, then sslVerifyHost=true will raise an exception. 311 | * `useGzip`: boolean - default=true. Use gzip compression for requests. 312 | * `connectTimeout`: integer - default=10. Max. time in seconds to connect to server. 313 | * `timeout`: default=30. Max. time in seconds to process request. 314 | 315 | ### loginToken($zabUrl, $zabToken, $options) 316 | 317 | Alternative login method using an API token, which is set directly as auth token. Options are the same as for `login()`. 318 | 319 | Since session management is not required with API tokens, no cached sessions are loaded or saved. 320 | 321 | * `return` void 322 | * `throws` ZabbixApiException. Invalid options, session issues or connection problems. 323 | * `param` string $zabUrl 324 | * `param` string $zabToken 325 | * `param` array $options - optional settings. 326 | 327 | ### call($method, $params) 328 | 329 | Execute Zabbix API call. Will automatically login/re-login and retry if the call failed using the current authKey read from session. 330 | 331 | > **Note:** Can only be called after login() was called once before at any time. 332 | 333 | * `return` mixed $reusedSession. Decoded Json response from API call or a scalar. See Zabbix API documentation for details. 334 | * `throws` ZabbixApiException. API Error, Session issues or connection problems. 335 | * `param` string $method. Zabbix API method i.e. 'host.get' 336 | * `param` mixed $params. Params as defined in the Zabbix API for that particular method. 337 | 338 | ### logout() 339 | 340 | Logout from Zabbix Server and also delete the authKey from filesystem. 341 | 342 | > **Note:** Only use this method if its really needed, because the session cannot be reused later on. Logouts on API object created with an API token have no effect. 343 | 344 | * `return` void 345 | * `throws` ZabbixApiException. API Error, Session issues or connection problems 346 | 347 | ### setDebug($state) 348 | 349 | Enable / Disable debug output. Can be used any time. 350 | 351 | * `return` void 352 | * `param` boolean $state. True enables debug output. 353 | 354 | ## Convenient functions 355 | 356 | ### getVersion() 357 | 358 | Get version of this library. 359 | 360 | * `return` string $version. 361 | 362 | ### getApiVersion() 363 | 364 | Get Zabbix API version from Zabbix Server. Also useful to check wether the Zabbix Api url is valid. 365 | 366 | > **Note:** Prefer this function over `call('apiinfo.version')`, because it does not try to authenticate and stores the Zabbix Api version for further requests. 367 | 368 | * `return` string $version. Uses API method 'apiinfo.version'. 369 | * `throws` ZabbixApiException. API Error, Session issues or connection problems 370 | 371 | ## Utility functions 372 | 373 | ### getAuthKey() 374 | 375 | Get authKey used for API communication. 376 | 377 | > **Note:** If there was no previous call to the Zabbix-API, this funcion will call the Zabbix-API to ensure a valid authkey. 378 | 379 | * `return` string $authKey. 380 | 381 | ### getSessionDir() 382 | 383 | Get session directory. 384 | 385 | * `return` string $directory. 386 | 387 | ### getSessionFileName() 388 | 389 | Get session FileName storing the encrypted authKey without path. 390 | 391 | * `return` string $fileName. 392 | 393 | ### getSessionFile() 394 | 395 | Get full FileName with path. 396 | 397 | * `return` string $fileName. 398 | 399 | # Tips and Tricks 400 | 401 | ## Common "get" method parameters 402 | 403 | As described in the [Zabbix-Api](https://www.zabbix.com/documentation/current/manual/api/reference_commentary), there several parameter that can be added to a "get" method. 404 | 405 | Find attached a list of some less known but quite useful ones, especially `preservekeys` : 406 | 407 | | Parameter | Type | Description | 408 | | :-------- | :--- | :---------- | 409 | | countOutput | boolean | Return the number of records in the result instead of the actual data. | 410 | | editable | boolean | If set to true return only objects that the user has write permissions to. Default: false. | 411 | | limit | integer | Limit the number of records returned. | 412 | | preservekeys | boolean | Use IDs as keys in the resulting array. | 413 | -------------------------------------------------------------------------------- /src/ZabbixApi.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright IntelliTrend GmbH, http://www.intellitrend.de 8 | * @license GNU Lesser General Public License v3.0 9 | * 10 | * You can redistribute this library and/or modify it under the terms of 11 | * the GNU LGPL as published by the Free Software Foundation, 12 | * either version 3 of the License, or any later version. 13 | * However you must not change author and copyright information. 14 | * 15 | * Implementation based on the offical Zabbix API docs. 16 | * Tested on Linux and Windows. 17 | * 18 | * Requires PHP 5.6+, JSON functions, CURL, Zabbix 3.0+ 19 | * For usage see examples provided in 'examples/' 20 | * 21 | * Errorhandling: 22 | * Errors are handled by exceptions. 23 | * - In case of ZabbxiApi errors, the msg and code is passed to the exception class ZabbixApiException 24 | * - In case of generic API errors, the code passed is defined by the constants: ZabbixApi::EXCEPTION_CLASS_CODE 25 | * - In case of session specfic API errors, the code passed is defined by the constants: ZabbixApi::EXCEPTION_CLASS_CODE_SESSION 26 | */ 27 | 28 | 29 | namespace IntelliTrend\Zabbix; 30 | 31 | class ZabbixApiException extends \Exception { 32 | public function __construct(string $message, int $code = 0, ?\Throwable $previous = null) { 33 | parent::__construct($message, $code, $previous); 34 | } 35 | } 36 | 37 | 38 | class ZabbixApi { 39 | 40 | const VERSION = "3.3.0"; 41 | 42 | const EXCEPTION_CLASS_CODE = 1000; 43 | const EXCEPTION_CLASS_CODE_SESSION = 2000; 44 | const SESSION_PREFIX = 'zbx_'; 45 | 46 | protected $zabUrl = ''; 47 | protected $zabUser = ''; 48 | protected $zabPassword = ''; 49 | protected $authKey = ''; 50 | protected $debug = false; 51 | protected $sessionDir = ''; // directory where to store the crypted session 52 | protected $sessionFileName = ''; // fileName of crypted session, depends on zabUrl/zabUser and SESSION_PREFIX 53 | protected $sessionFile = ''; // directory + / + fileName 54 | protected $sslCaFile = ''; // set external CA bundle. If not set use php.ini default settings. See https://curl.haxx.se/docs/caextract.html 55 | protected $sslVerifyPeer = 1; // verify cert 56 | protected $sslVerifyHost = 2; // if cert is valid, check hostname 57 | protected $useGzip = true; 58 | protected $timeout = 30; //max. time in seconds to process request 59 | protected $connectTimeout = 10; //max. time in seconds to connect to server 60 | protected $authKeyIsValid = false; // whether the autkey was actually successfully used in this session 61 | protected $authKeyIsToken = false; // whether the autkey is a token and therefore not bound to a session 62 | protected $authHeader = false; // whether the authkey should be send as header or inside the body 63 | protected $userKey = ''; // name of the username field 64 | protected $zabApiVersion = ''; // Zabbix API version. Updated when calling getApiVersion() or on first _login() attempt. Needed for API change in 5.4 (user -> username) 65 | 66 | 67 | /** 68 | * Constructor 69 | * Check for required Curl module 70 | * @throws ZabbixApiException 71 | */ 72 | public function __construct() { 73 | if (!function_exists('curl_init')) { 74 | throw new ZabbixApiException("Missing Curl support. Install the PHP Curl module.", ZabbixApi::EXCEPTION_CLASS_CODE); 75 | } 76 | } 77 | 78 | 79 | /** 80 | * Login - setup internal structure and validate sessionDir 81 | * 82 | * @param string $zabUrl - Zabbix base URL 83 | * @param string $zabUser - Zabbix user name 84 | * @param string $zabPassword - Zabbix password 85 | * @param array $options - optional settings. Example: array('sessionDir' => '/tmp', 'sslVerifyPeer' => true, 'useGzip' => true, 'debug' => true); 86 | * @throws ZabbixApiException 87 | */ 88 | public function login($zabUrl, $zabUser, $zabPassword, $options = array()) { 89 | 90 | $zabUrl = substr($zabUrl , -1) == '/' ? $zabUrl : $zabUrl .= '/'; 91 | $this->zabUrl = $zabUrl; 92 | 93 | $this->zabUser = $zabUser; 94 | $this->zabPassword = $zabPassword; 95 | 96 | $this->applyOptions($options); 97 | 98 | // if sessionDir is passed as param check if a directory exists. otherwise use the default temp directory 99 | if (array_key_exists('sessionDir', $options)) { 100 | $sessionDir = $options['sessionDir']; 101 | if (!is_dir($sessionDir)) { 102 | throw new ZabbixApiException("Error - sessionDir:$sessionDir is not a valid directory", ZabbixApi::EXCEPTION_CLASS_CODE); 103 | } 104 | if (!is_writable($sessionDir)) { 105 | throw new ZabbixApiException("Error - sessionDir:$sessionDir is not a writeable directory", ZabbixApi::EXCEPTION_CLASS_CODE); 106 | } 107 | $this->sessionDir = $sessionDir; 108 | } 109 | else { 110 | $this->sessionDir = sys_get_temp_dir(); 111 | } 112 | 113 | $sessionFileName = ZabbixApi::SESSION_PREFIX. md5($this->zabUrl . $this->zabUser); 114 | $this->sessionFileName = $sessionFileName; 115 | $this->sessionFile = $this->sessionDir. '/'. $this->sessionFileName; 116 | 117 | if ($this->debug) { 118 | print "DBG login(). Using sessionDir:$this->sessionDir, sessionFileName:$this->sessionFileName\n"; 119 | } 120 | 121 | $sessionAuthKey = $this->readAuthKeyFromSession(); 122 | 123 | // check API version first to set version-specific flags 124 | $this->getApiVersion(); 125 | 126 | // When debug is enabled, we want to see if the session has been reused. This requires a call to the Zabbix-API. 127 | if ($this->debug) { 128 | $this->call('user.get', array('output' => 'userid', 'limit' => 1)); 129 | if ($this->authKey == $sessionAuthKey) { 130 | print "DBG login(). Re-Using existing session\n"; 131 | } else { 132 | print "DBG login(). Creating new session\n"; 133 | } 134 | } 135 | } 136 | 137 | /** 138 | * Login - setup internal structure via API token 139 | * 140 | * @param string $zabUrl - Zabbix base URL 141 | * @param string $zabToken - Zabbix API token 142 | * @param array $options - optional settings. Example: array('sessionDir' => '/tmp', 'sslVerifyPeer' => true, 'useGzip' => true, 'debug' => true); 143 | * @throws ZabbixApiException 144 | */ 145 | public function loginToken($zabUrl, $zabToken, $options = array()) { 146 | 147 | $zabUrl = substr($zabUrl , -1) == '/' ? $zabUrl : $zabUrl .= '/'; 148 | $this->zabUrl = $zabUrl; 149 | 150 | // login fields are unused with tokens 151 | $this->zabUser = ''; 152 | $this->zabPassword = ''; 153 | 154 | $this->applyOptions($options); 155 | 156 | // session files are also not required 157 | $this->sessionDir = ''; 158 | $this->sessionFileName = ''; 159 | $this->sessionFile = ''; 160 | 161 | // use token directly as auth key 162 | $this->authKey = $zabToken; 163 | $this->authKeyIsValid = true; 164 | $this->authKeyIsToken = true; 165 | 166 | // check API version first to set version-specific flags 167 | $this->getApiVersion(); 168 | } 169 | 170 | 171 | /** 172 | * Convenient function to get remote API version 173 | * 174 | * @return string $apiVersion 175 | */ 176 | public function getApiVersion() { 177 | $this->zabApiVersion = $this->callZabbixApi('apiinfo.version'); 178 | // Zabbix version 5.4 changed key 'user' -> 'username' 179 | if (version_compare($this->zabApiVersion, '5.2.0', '>')) { 180 | $this->userKey = 'username'; 181 | } else { 182 | $this->userKey = 'user'; 183 | } 184 | // Zabbix has deprecated the auth field inside body in 6.4 and removed it in 7.2 185 | $this->authHeader = version_compare($this->zabApiVersion, '6.4.0', '>'); 186 | return $this->zabApiVersion; 187 | } 188 | 189 | 190 | /** 191 | * Get version of this library 192 | * 193 | * @return string $version 194 | */ 195 | public function getVersion() { 196 | return Zabbixapi::VERSION; 197 | } 198 | 199 | 200 | /** 201 | * Get authKey used for API communication - Supportfunction, not used internally 202 | * If there was no call to the Zabbix-API before, this function will call the Zabbix-API 203 | * to ensure a valid $authKey. 204 | * @return string $authKey 205 | */ 206 | public function getAuthKey() { 207 | // if there was no login to the Zabbix-API so far, we do not know wether the key is valid 208 | if (!$this->authKeyIsValid && !$this->authKeyIsToken) { 209 | // Simple call that requires Authentication - will update the key if needed. 210 | $this->call('user.get', array('output' => 'userid', 'limit' => 1)); 211 | } 212 | return $this->authKey; 213 | } 214 | 215 | 216 | /** 217 | * Enable / Disable debug 218 | * 219 | * @param boolean $status. True = enable 220 | */ 221 | public function setDebug($status) { 222 | $this->debug = $status && 1; 223 | } 224 | 225 | 226 | /** 227 | * Logout from Zabbix Server and delete the session from filesystem 228 | * 229 | * Only use this method if its really needed, because you cannot reuse the session later on. 230 | */ 231 | public function logout() { 232 | if ($this->debug) { 233 | print "DBG logout(). Delete sessionFile and logout from Zabbix\n"; 234 | } 235 | 236 | // token-based sessions can't logout 237 | if ($this->authKeyIsToken) { 238 | return; 239 | } 240 | 241 | $response = $this->callZabbixApi('user.logout'); 242 | // remove session locally - ignore if session no longer exists 243 | $ret = unlink($this->getSessionFile()); 244 | } 245 | 246 | 247 | /** 248 | * Get session directory 249 | * 250 | * @return string $sessionDir 251 | */ 252 | public function getSessionDir() { 253 | return $this->sessionDir; 254 | } 255 | 256 | /** 257 | * Get session FileName without path 258 | * 259 | * @return string $sessionFileName 260 | */ 261 | public function getSessionFileName() { 262 | return $this->sessionFileName; 263 | } 264 | 265 | 266 | /** 267 | * Get full FileName with path 268 | * 269 | * @return string $sessionFile 270 | */ 271 | public function getSessionFile() { 272 | return $this->sessionFile; 273 | } 274 | 275 | 276 | /** 277 | * High level Zabbix Api call. Will automatically re-login and retry if call failed using the current authKey. 278 | * 279 | * Note: Can only be called after login() was called once before at any time. 280 | * 281 | * @param string $method. Zabbix API method i.e. 'host.get' 282 | * @param mixed $params. Params as defined in the Zabbix API for that particular method 283 | * @return mixed $response. Decoded Json response or scalar 284 | * @throws ZabbixApiException 285 | */ 286 | public function call($method, $params = array()) { 287 | if (!$this->zabUrl) { 288 | throw new ZabbixApiException("Missing Zabbix URL.", ZabbixApi::EXCEPTION_CLASS_CODE); 289 | } 290 | 291 | // for token-based auth, pass through to callZabbixApi 292 | if ($this->authKeyIsToken) { 293 | return $this->callZabbixApi($method, $params); 294 | } 295 | 296 | // for classic login, try to call API with existing auth first 297 | try { 298 | return $this->callZabbixApi($method, $params); 299 | } 300 | catch (ZabbixApiException $e) { 301 | // check for session exception 302 | if ($e->getCode() == ZabbixApi::EXCEPTION_CLASS_CODE_SESSION) { 303 | // renew session and retry call 304 | $this->__login(); 305 | return $this->callZabbixApi($method, $params); 306 | } else { 307 | // re-throw any other exception 308 | throw $e; 309 | } 310 | } 311 | 312 | // technically unreachable, but just in case 313 | return NULL; 314 | } 315 | 316 | 317 | /*************** Protected / Private functions ***************/ 318 | 319 | 320 | /** 321 | * Internal login function to perform the login. Saves authKey to sessionFile on success. 322 | * 323 | * @return boolean $success 324 | */ 325 | protected function __login() { 326 | // Try to login to our API 327 | if ($this->debug) { 328 | print "DBG __login(). Called\n"; 329 | } 330 | $response = $this->callZabbixApi('user.login', array( 'password' => $this->zabPassword, $this->userKey => $this->zabUser)); 331 | 332 | if (isset($response) && strlen($response) == 32) { 333 | $this->authKey = $response; 334 | //on successful login save authKey to session 335 | $this->writeAuthKeyToSession(); 336 | $this->authKeyIsValid = true; 337 | return true; 338 | } 339 | 340 | // login failed 341 | $this->authKey = ''; 342 | $this->authKeyIsValid = false; 343 | return false; 344 | } 345 | 346 | 347 | /** 348 | * Internal call to Zabbix API via RPC/API call 349 | * 350 | * @param string $method 351 | * @param mixed $params 352 | * @return mixed $response. Json decoded response 353 | * @throws ZabbixApiException 354 | */ 355 | protected function callZabbixApi($method, $params = array()) { 356 | $authRequired = $method != 'user.login' && $method != 'apiinfo.version'; 357 | 358 | if (!$this->authKey && $authRequired) { 359 | throw new ZabbixApiException("Not logged in and no authKey", ZabbixApi::EXCEPTION_CLASS_CODE_SESSION); 360 | } 361 | 362 | $request = $this->buildRequest($method, $params, $authRequired && !$this->authHeader); 363 | $rawResponse = $this->executeRequest($this->zabUrl.'api_jsonrpc.php', $request, $authRequired && $this->authHeader); 364 | 365 | if ($this->debug) { 366 | print "DBG callZabbixApi(). Raw response from API: $rawResponse\n"; 367 | } 368 | $response = json_decode($rawResponse, true); 369 | 370 | if ( isset($response['id']) && $response['id'] == 1 && isset($response['result']) ) { 371 | $this->authKeyIsValid = true; 372 | return $response['result']; 373 | } 374 | 375 | if (is_array($response) && array_key_exists('error', $response)) { 376 | $code = $response['error']['code']; 377 | $message = $response['error']['message']; 378 | $data = $response['error']['data']; 379 | $msg = "$message [$data]"; 380 | throw new ZabbixApiException($msg, $code); 381 | } 382 | 383 | $msg = "Error without further information."; 384 | throw new ZabbixApiException($msg); 385 | 386 | } 387 | 388 | 389 | /** 390 | * Build the Zabbix JSON-RPC request 391 | * 392 | * @param string $method 393 | * @param mixed $params 394 | * @param bool $useAuth. Include auth field 395 | * @return string $request. Json encoded request object 396 | * @throws ZabbixApiException 397 | */ 398 | protected function buildRequest($method, $params = array(), $useAuth = true) { 399 | if ($params && !is_array($params)) { 400 | throw new ZabbixApiException("Params passed to API call must be an array", ZabbixApi::EXCEPTION_CLASS_CODE); 401 | } 402 | 403 | $request = array( 404 | 'method' => $method, 405 | 'id' => 1, // since we do not work in parallel, always using the same id should work 406 | 'params' => ( is_array($params) ? $params : array() ), 407 | 'jsonrpc' => "2.0" 408 | ); 409 | 410 | // required up to Zabbix 6.2 411 | if ($useAuth) { 412 | $request['auth'] = $this->authKey; 413 | } 414 | 415 | return json_encode($request); 416 | } 417 | 418 | 419 | /** 420 | * Low level execute the request 421 | * 422 | * @param string $zabUrl. Url pointing to API endpoint 423 | * @param bool $useAuth. Include authorization header 424 | * @param mixed $data. 425 | * @return string $response. Json encoded response from API 426 | */ 427 | protected function executeRequest($zabUrl, $data = '', $useAuth = true) { 428 | $c = curl_init($zabUrl); 429 | // These are required for submitting JSON-RPC requests 430 | 431 | $headers = array(); 432 | $headers[] = 'Content-Type: application/json-rpc'; 433 | $headers[] = 'User-Agent: IntelliTrend/ZabbixApi;Version:'. Zabbixapi::VERSION; 434 | 435 | // required starting with Zabbix 7.2 436 | if ($useAuth) { 437 | $headers[] = 'Authorization: Bearer '.$this->authKey; 438 | } 439 | 440 | $opts = array( 441 | // allow to return a curl handle 442 | CURLOPT_RETURNTRANSFER => true, 443 | // max number of seconds to allow curl to process the request 444 | CURLOPT_TIMEOUT => $this->timeout, 445 | // max number of seconds to establish a connection 446 | CURLOPT_CONNECTTIMEOUT => $this->connectTimeout, 447 | // ensure the certificate itself is valid (signed by a trusted CA, the certificate chain is complete, etc.) 448 | CURLOPT_SSL_VERIFYPEER => $this->sslVerifyPeer, 449 | // 0 or 2. Ensure the host connecting to is the host named in the certificate. 450 | CURLOPT_SSL_VERIFYHOST => $this->sslVerifyHost, 451 | // follow if url has changed 452 | CURLOPT_FOLLOWLOCATION => true, 453 | // no cached connection or responses 454 | CURLOPT_FRESH_CONNECT => true 455 | ); 456 | 457 | 458 | $opts[CURLOPT_HTTPHEADER] = $headers; 459 | 460 | $opts[CURLOPT_CUSTOMREQUEST] = "POST"; 461 | $opts[CURLOPT_POSTFIELDS] = ( is_array($data) ? http_build_query($data) : $data ); 462 | 463 | // use compression 464 | $opts[CURLOPT_ENCODING] = 'gzip'; 465 | 466 | if ($this->debug) { 467 | print "DBG executeRequest(). CURL Params: ". $opts[CURLOPT_POSTFIELDS]. "\n"; 468 | } 469 | 470 | curl_setopt_array($c, $opts); 471 | // pass CAs if set 472 | if ($this->sslCaFile != '') { 473 | curl_setopt($c, CURLOPT_CAINFO, $this->sslCaFile); 474 | } 475 | 476 | $response = @curl_exec($c); 477 | $info = curl_getinfo($c); 478 | $sslErrorMsg = curl_error($c); 479 | 480 | $httpCode = $info['http_code']; 481 | $sslVerifyResult = $info['ssl_verify_result']; 482 | 483 | if ( $httpCode == 0 || $httpCode >= 400) { 484 | throw new ZabbixApiException("Request failed with HTTP-Code:$httpCode, sslVerifyResult:$sslVerifyResult. $sslErrorMsg", $httpCode); 485 | } 486 | 487 | 488 | if ( $sslVerifyResult != 0 && $this->sslVerifyPeer == 1) { 489 | $error = curl_error($c); 490 | throw new ZabbixApiException("Request failed with SSL-Verify-Result:$sslVerifyResult. $sslErrorMsg", $sslVerifyResult); 491 | } 492 | 493 | curl_close($c); 494 | return $response; 495 | } 496 | 497 | 498 | /** 499 | * Read encrypted authKey from session-file, decrpyt and save it in the class instance 500 | * 501 | * @return string authKey. Empty string '' if authKey was not found. 502 | */ 503 | protected function readAuthKeyFromSession() { 504 | $sessionFile = $this->getSessionFile(); 505 | 506 | // if no session exist simply return 507 | $fh = @fopen($sessionFile, "r"); 508 | if ($fh == false) { 509 | if ($this->debug) { 510 | print "DBG readAuthKeyFromSession(). sessionFile not found. sessionFile:$sessionFile\n"; 511 | } 512 | return ''; 513 | } 514 | 515 | $encryptedKey = fread($fh, filesize($sessionFile)); 516 | if (!$encryptedKey) { 517 | return ''; 518 | } 519 | 520 | fclose($fh); 521 | 522 | $authKey = $this->decryptAuthKey($encryptedKey); 523 | 524 | if (!$authKey) { 525 | if ($this->debug) { 526 | print "DBG readAuthKeyFromSession(). Decrypting authKey from sessionFile failed. sessionFile:$sessionFile\n"; 527 | } 528 | $this->authKey = ''; 529 | return NULL; 530 | } 531 | 532 | 533 | if ($this->debug) { 534 | print "DBG readAuthKeyFromSession(). Read authKey:$authKey from sessionFile:$sessionFile\n"; 535 | } 536 | 537 | // save to class instance 538 | $this->authKey = $authKey; 539 | return $authKey; 540 | } 541 | 542 | 543 | /** 544 | * Write authKey encrypted to the session-file 545 | * 546 | * @return true 547 | * @throws exeception 548 | */ 549 | protected function writeAuthKeyToSession() { 550 | //write content 551 | $sessionFile = $this->getSessionFile(); 552 | 553 | $fh = fopen($sessionFile, "w"); 554 | if ($fh == false) { 555 | throw new ZabbixApiException("Cannot open sessionFile. sessionFile:$sessionFile", ZabbixApi::EXCEPTION_CLASS_CODE); 556 | } 557 | 558 | $encryptedKey = $this->encryptAuthKey($this->authKey); 559 | 560 | if (fwrite($fh, $encryptedKey) == false) { 561 | throw new ZabbixApiException("Cannot write encrypted authKey to sessionFile. sessionFile:$sessionFile", ZabbixApi::EXCEPTION_CLASS_CODE); 562 | } 563 | 564 | fclose($fh); 565 | 566 | if ($this->debug) { 567 | print "DBG writeAuthKeyToSession(). Saved encrypted authKey:$encryptedKey to sessionFile:$sessionFile\n"; 568 | } 569 | 570 | return true; 571 | } 572 | 573 | 574 | /** 575 | * Encrypt authKey 576 | * 577 | * @param string $authKey (plain) 578 | * @return string $encryptedKey 579 | */ 580 | protected function encryptAuthKey($authKey) { 581 | $encryptedAuthKey = base64_encode(openssl_encrypt( 582 | $authKey, 583 | "aes-128-cbc", 584 | hash("SHA256", $this->zabUser. $this->zabPassword, true), 585 | OPENSSL_RAW_DATA, 586 | "1356647968472110" 587 | )); 588 | 589 | return $encryptedAuthKey; 590 | } 591 | 592 | 593 | /** 594 | * Decrypt authKey 595 | * 596 | * @param string $encryptedAuthKey 597 | * @return string $authKey. If decryption fails key is empty "" 598 | */ 599 | protected function decryptAuthKey($encryptedAuthKey) { 600 | $authKey = openssl_decrypt(base64_decode($encryptedAuthKey), 601 | "aes-128-cbc", 602 | hash("SHA256", $this->zabUser. $this->zabPassword, true), 603 | OPENSSL_RAW_DATA, 604 | "1356647968472110" 605 | ); 606 | 607 | return $authKey; 608 | } 609 | 610 | /** 611 | * Internal function to apply options from an associative array. 612 | */ 613 | protected function applyOptions($options) { 614 | $validOptions = array('debug', 'sessionDir', 'sslCaFile', 'sslVerifyHost', 'sslVerifyPeer', 'useGzip', 'timeout', 'connectTimeout'); 615 | foreach ($options as $k => $v) { 616 | if (!in_array($k, $validOptions)) { 617 | throw new ZabbixApiException("Invalid option used. option:$k", ZabbixApi::EXCEPTION_CLASS_CODE); 618 | } 619 | } 620 | 621 | 622 | if (array_key_exists('debug', $options)) { 623 | $this->debug = $options['debug'] && true; 624 | } 625 | 626 | if ($this->debug) { 627 | print "DBG login(). Using zabUser:$this->zabUser, zabUrl:$this->zabUrl\n"; 628 | print "DBG login(). Library Version:". ZabbixApi::VERSION. "\n"; 629 | } 630 | 631 | if (array_key_exists('sslCaFile', $options)) { 632 | if (!is_file($options['sslCaFile'])) { 633 | throw new ZabbixApiException("Error - sslCaFile:". $options['sslCaFile']. " is not a valid file", ZabbixApi::EXCEPTION_CLASS_CODE); 634 | } 635 | $this->sslCaFile = $options['sslCaFile']; 636 | } 637 | 638 | if (array_key_exists('sslVerifyPeer', $options)) { 639 | $this->sslVerifyPeer = ($options['sslVerifyPeer']) ? 1 : 0; 640 | } 641 | 642 | if (array_key_exists('sslVerifyHost', $options)) { 643 | $this->sslVerifyHost = ($options['sslVerifyHost']) ? 2 : 0; 644 | } 645 | 646 | if (array_key_exists('useGzip', $options)) { 647 | $this->useGzip = ($options['useGzip']) ? true : false; 648 | } 649 | 650 | if (array_key_exists('timeout', $options)) { 651 | $this->timeout = (intval($options['timeout']) > 0)? $options['timeout'] : 30; 652 | } 653 | 654 | if (array_key_exists('connectTimeout', $options)) { 655 | $this->connectTimeout = (intval($options['connectTimeout']) > 0)? $options['connectTimeout'] : 30; 656 | } 657 | 658 | if ($this->debug) { 659 | print "DBG login(). Using sslVerifyPeer:". $this->sslVerifyPeer . " sslVerifyHost:". $this->sslVerifyHost. " useGzip:". $this->useGzip. " timeout:". $this->timeout. " connectTimeout:". $this->connectTimeout. "\n"; 660 | } 661 | } 662 | } 663 | --------------------------------------------------------------------------------