├── .gitmodules
├── README.md
└── php-client
├── .gitignore
├── api-config.dist.php
├── class.phpipam-api.php
└── example.php
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "powershell-client"]
2 | path = powershell-client
3 | url = https://github.com/yoke88/PSPHPIPAM.git
4 | [submodule "phpipam-pyclient"]
5 | path = phpipam-pyclient
6 | url = https://github.com/viniarck/phpipam-pyclient.git
7 | [submodule "phpipamsdk"]
8 | path = phpipamsdk
9 | url = https://github.com/efenian/phpipamsdk.git
10 | [submodule "python-phpipam"]
11 | path = python-phpipam
12 | url = https://github.com/kompetenzbolzen/python-phpipam
13 | [submodule "phpypam"]
14 | path = phpypam
15 | url = https://github.com/codeaffen/phpypam.git
16 | [submodule "phpipam-ansible-modules"]
17 | path = phpipam-ansible-modules
18 | url = https://github.com/codeaffen/phpipam-ansible-modules.git
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## phpipam-api-clients
2 |
3 | Collection of phpipam API clients in various languages to use with phpIPAM API server.
4 |
--------------------------------------------------------------------------------
/php-client/.gitignore:
--------------------------------------------------------------------------------
1 | api-config.php
2 | token.txt
3 |
--------------------------------------------------------------------------------
/php-client/api-config.dist.php:
--------------------------------------------------------------------------------
1 | dont save, check each time
17 | # filename => will save token to filename provided
18 | $token_file = "token.txt";
19 |
20 | # set result format json/object/array/xml
21 | $result_format = "json";
22 |
23 | ?>
--------------------------------------------------------------------------------
/php-client/class.phpipam-api.php:
--------------------------------------------------------------------------------
1 | "OK",
151 | 201 => "Created",
152 | 202 => "Accepted",
153 | 204 => "No Content",
154 | // Client errors
155 | 400 => "Bad Request",
156 | 401 => "Unauthorized",
157 | 403 => "Forbidden",
158 | 404 => "Not Found",
159 | 405 => "Method Not Allowed",
160 | 415 => "Unsupported Media Type",
161 | // Server errors
162 | 500 => "Internal Server Error",
163 | 501 => "Not Implemented",
164 | 503 => "Service Unavailable",
165 | 505 => "HTTP Version Not Supported",
166 | 511 => "Network Authentication Required"
167 | );
168 |
169 | /**
170 | * Set result format
171 | *
172 | * (default value: array("json", "array", "object", "xml"))
173 | *
174 | * @var string
175 | * @access private
176 | */
177 | private $result_format_available = array("json", "array", "object", "xml");
178 |
179 | /**
180 | * Result format
181 | *
182 | * json/array/object/xml
183 | *
184 | * (default value: "json")
185 | *
186 | * @var string
187 | * @access private
188 | */
189 | private $result_format = "json";
190 |
191 | /**
192 | * To store result
193 | *
194 | * @var mixed
195 | * @access private
196 | */
197 | public $result = array(
198 | "success" => true,
199 | "code" => 204,
200 | "message" => ""
201 | );
202 |
203 | /**
204 | * Reponse headers
205 | *
206 | * @var array
207 | */
208 | public $response_headers = array ();
209 |
210 |
211 |
212 |
213 | /**
214 | * __construct function.
215 | *
216 | * @access public
217 | * @param bool|mixed $api_url (default: false)
218 | * @param bool|mixed $app_id (default: false)
219 | * @param bool|mixed $api_key (default: false)
220 | * @param bool|mixed $username (default: false)
221 | * @param bool|mixed $password (default: false)
222 | * @param mixed $result_format (default: "json")
223 | */
224 | public function __construct($api_url = false, $app_id = false, $api_key = false, $username = false, $password = false, $result_format = "json") {
225 | // set app server URL if provided
226 | if ($api_url!==false) {
227 | $this->set_api_url ($api_url);
228 | }
229 | // set app_id if provided
230 | if ($app_id!==false) {
231 | $this->set_api_app_id ($app_id);
232 | }
233 | // set api key if provided
234 | if ($api_key!==false) {
235 | $this->set_api_key ($api_key);
236 | }
237 | // set user/pass if provided
238 | if ($username!==false && $password!==false) {
239 | $this->set_api_authparams ($username, $password);
240 | }
241 | // set result format if provided
242 | if (strlen($result_format)>0) {
243 | $this->set_result_format ($result_format);
244 | }
245 | // check for required php extensions
246 | $this->validate_php_extensions ();
247 | }
248 |
249 | /**
250 | * Saves error and exits script
251 | *
252 | * @access public
253 | * @param mixed $content
254 | * @return void
255 | */
256 | public function exception ($content) {
257 | //set result parameters
258 | $this->result = array(
259 | 'code' => 400,
260 | 'success' => false,
261 | 'message' => $content
262 | );
263 | // print result
264 | $this->print_result ();
265 | // die
266 | die();
267 | }
268 |
269 | /**
270 | * Returns last result
271 | *
272 | * @access public
273 | * @return void
274 | */
275 | public function get_result () {
276 | # output result
277 | if ($this->result_format=="json") {
278 | return json_encode($this->result);
279 | }
280 | elseif ($this->result_format=="array") {
281 | return $this->result;
282 | }
283 | elseif ($this->result_format=="object") {
284 | return (object) $this->result;
285 | }
286 | elseif ($this->result_format=="xml") {
287 | // new SimpleXMLElement object
288 | $xml = new SimpleXMLElement('<'.$_GET['controller'].'/>');
289 | // generate xml from result
290 | $this->array_to_xml($xml, $this->result);
291 | // return XML result
292 | return $xml->asXML();
293 | }
294 | }
295 |
296 | /**
297 | * Prints last result
298 | *
299 | * @access public
300 | * @return void
301 | */
302 | public function print_result () {
303 | # output result
304 | if ($this->result_format=="json") {
305 | print json_encode($this->result);
306 | }
307 | elseif ($this->result_format=="array") {
308 | var_dump($this->result);
309 | }
310 | elseif ($this->result_format=="object") {
311 | var_dump( (object) $this->result);
312 | }
313 | elseif ($this->result_format=="xml") {
314 | // new SimpleXMLElement object
315 | $xml = new SimpleXMLElement('');
316 | // generate xml from result
317 | $this->array_to_xml($xml, $this->result);
318 | // return XML result
319 | print $xml->asXML();
320 | }
321 | }
322 |
323 | /**
324 | * Transforms array to XML
325 | *
326 | * @access private
327 | * @param SimpleXMLElement $object
328 | * @param array $data
329 | * @return void
330 | */
331 | private function array_to_xml(SimpleXMLElement $object, array $data) {
332 | // loop through values
333 | foreach ($data as $key => $value) {
334 | // if spaces exist in key replace them with underscores
335 | if(strpos($key, " ")>0) { $key = str_replace(" ", "_", $key); }
336 |
337 | // if key is numeric append item
338 | if(is_numeric($key)) $key = "item".$key;
339 |
340 | // if array add child
341 | if (is_array($value)) {
342 | $new_object = $object->addChild($key);
343 | $this->array_to_xml($new_object, $value);
344 | }
345 | // else write value
346 | else {
347 | $object->addChild($key, $value);
348 | }
349 | }
350 | }
351 |
352 | /**
353 | * Check if all extensions are present
354 | *
355 | * @access private
356 | * @return void
357 | */
358 | private function validate_php_extensions () {
359 | // Required extensions
360 | $required_ext = array("openssl", "curl");
361 | // mcrypt for crypted extensions
362 | if($this->api_key !== false)
363 | $required_ext[] = "mcrypt";
364 | // json
365 | if($this->result_format == "json")
366 | $required_ext[] = "json";
367 | // xml
368 | if($this->result_format == "xml")
369 | $required_ext[] = "xmlreader";
370 |
371 | // Available extensions
372 | $available_ext = get_loaded_extensions();
373 |
374 | // check
375 | foreach ($required_ext as $e) {
376 | if(!in_array($e, $available_ext)) {
377 | $this->exception("Missing php extension ($e)");
378 | }
379 | }
380 | }
381 |
382 | /**
383 | * Debugging flag
384 | *
385 | * @access public
386 | * @param bool $debug (default: false)
387 | * @return void
388 | */
389 | public function set_debug ($debug = false) {
390 | if(is_bool($debug)) {
391 | $this->debug = $debug;
392 | }
393 | }
394 |
395 | /**
396 | * Checks requested result format and saves it
397 | *
398 | * @access public
399 | * @param string $result_format (default: "json")
400 | * @return void
401 | */
402 | public function set_result_format ($result_format = "json") {
403 | if (strlen($result_format)>0) {
404 | if (!in_array($result_format, $this->result_format_available)) {
405 | $this->exception ("Invalid result format");
406 | }
407 | else {
408 | // recheck extensions
409 | $this->validate_php_extensions ();
410 | // set
411 | $this->result_format = $result_format;
412 | }
413 | }
414 | }
415 |
416 | /**
417 | * Set API url parameter
418 | *
419 | * @access public
420 | * @param mixed $api_url
421 | * @return void
422 | */
423 | public function set_api_url ($api_url) {
424 | // we need http/https
425 | if(strpos($api_url, "http://")!==false || strpos($api_url, "https://")!==false) {
426 | // trim
427 | $api_url = trim($api_url);
428 | // add last / if missing
429 | if (substr($api_url, -1)!=="/") { $api_url .= "/"; }
430 | // save
431 | $this->api_url = $api_url;
432 | }
433 | else {
434 | $this->exception("Invalid APP id");
435 | }
436 | }
437 |
438 | /**
439 | * Sets api app_id variable
440 | *
441 | * @access public
442 | * @param bool $id (default: false)
443 | * @return void
444 | */
445 | public function set_api_app_id ($app_id = false) {
446 | if ($app_id!==false) {
447 | // name must be more than 2 and alphanumberic
448 | if(strlen($app_id)<3 || strlen($app_id)>12 || !ctype_alnum($app_id)) {
449 | $this->exception("Invalid APP id");
450 | }
451 | else {
452 | $this->api_app_id = $app_id;
453 | }
454 | }
455 | else {
456 | $this->exception("Invalid APP id");
457 | }
458 | }
459 |
460 | /**
461 | * Set api key
462 | *
463 | * @access public
464 | * @param bool $api_key (default: false)
465 | * @return void
466 | */
467 | public function set_api_key ($api_key = false) {
468 | if ($api_key!==false) {
469 | $this->api_key = $api_key;
470 |
471 | // set encrypt flag
472 | $this->api_encrypt = true;
473 | }
474 | else {
475 | $this->exception("Invalid APP id");
476 | }
477 | }
478 |
479 | /**
480 | * Sets username/password for URL auth
481 | *
482 | * @access public
483 | * @param bool $username (default: false)
484 | * @param bool $password (default: false)
485 | * @return void
486 | */
487 | public function set_api_authparams ($username = false, $password = false) {
488 | if($username===false || $password===false) {
489 | $this->exception("Invalid username or password");
490 | }
491 | else {
492 | $this->api_username = $username;
493 | $this->api_password = $password;
494 | }
495 | }
496 |
497 | /**
498 | * Sreets api method.
499 | *
500 | * @access public
501 | * @param string $method (default: "GET")
502 | * @return void
503 | */
504 | public function set_api_method ($method = "GET") {
505 | // validate
506 | $this->set_api_method_validate ($method);
507 | // set
508 | $this->api_server_method = strtoupper($method);
509 | }
510 |
511 | /**
512 | * Validates API method against available
513 | *
514 | * @access private
515 | * @param mixed $method
516 | * @return void
517 | */
518 | private function set_api_method_validate ($method) {
519 | if(!in_array(strtoupper($method), $this->api_server_valid_methods)) {
520 | $this->exception("Invalid method $method");
521 | }
522 | }
523 |
524 | /**
525 | * Sets API controller - required
526 | *
527 | * @access public
528 | * @param bool $controller (default: false)
529 | * @return void
530 | */
531 | public function set_api_controller ($controller = false) {
532 | if($controller!==false) {
533 | $this->api_server_controller = strtolower($controller);
534 | }
535 | }
536 |
537 | /**
538 | * Sets additional identifiers to be passed to URL directly
539 | *
540 | * e.g.: /api/appid/controller///
541 | *
542 | * @access public
543 | * @param mixed $identifiers
544 | * @return void
545 | */
546 | public function set_api_identifiers ($identifiers) {
547 | $this->api_server_identifiers = false; // clear this to forget any previous settings
548 | if(is_array($identifiers)) {
549 | if(sizeof($identifiers)>0 && !$this->api_encrypt) {
550 | // reset
551 | $this->api_server_identifiers = implode("/", $identifiers);
552 | }
553 | elseif (sizeof($identifiers)>0 && $this->api_encrypt) {
554 | $this->api_server_identifiers = array();
555 | foreach ($identifiers as $cnt=>$i) {
556 | if($cnt==0) { $this->api_server_identifiers['id'] = $i; }
557 | else { $this->api_server_identifiers['id'.($cnt+1)] = $i; }
558 | }
559 |
560 | }
561 | }
562 | }
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 | /* @api-server communication --------------- */
575 |
576 | /**
577 | * Executes request to API server
578 | *
579 | * @access public
580 | * @param bool $method (default: false)
581 | * @param bool $controller (default: false)
582 | * @param array $identifiers (default: array())
583 | * @param array $params (default: array())
584 | * @param bool $token_file (default: false)
585 | * @return void
586 | */
587 | public function execute ($method = false, $controller = false, $identifiers = array(), $params = array(), $token_file = false) {
588 | // check and set method
589 | $this->set_api_method ($method);
590 | // set api controller
591 | $this->set_api_controller ($controller);
592 | // set api identifiers
593 | $this->set_api_identifiers ($identifiers);
594 |
595 | // set connection
596 | $this->curl_set_connection ($token_file);
597 | // save params
598 | $this->curl_set_params ($params);
599 | // set HTTP method
600 | $this->curl_set_http_method ();
601 |
602 | // if not encrypted set params
603 | if(!$this->api_encrypt) {
604 | // add token to header, authenticate if it fails
605 | $this->curl_add_token_header ($token_file);
606 | }
607 | // if token is set execute
608 | if ($this->token !== false) {
609 | // execute
610 | $res = $this->curl_execute ();
611 | // save result
612 | $this->result = (array) $res;
613 |
614 | // check for invalid token and retry
615 | if ($this->result['code']=="401" && $token_file!==false) {
616 | // remove old token
617 | $this->delete_token_file ($token_file);
618 | // auth again
619 | $this->curl_add_token_header ($token_file);
620 | // execute
621 | $res = $this->curl_execute ();
622 | // save result
623 | $this->result = (array) $res;
624 | }
625 | }
626 | // exncrypted request
627 | elseif ($this->api_encrypt) {
628 | // execute
629 | $res = $this->curl_execute ();
630 | // save result
631 | $this->result = (array) $res;
632 | }
633 | // save reult
634 | $this->curl_save_headers ();
635 | }
636 |
637 | /**
638 | * Opens cURL resource and sets initial parameters
639 | *
640 | * @access private
641 | * @param mixed $token_file
642 | * @return void
643 | */
644 | private function curl_set_connection ($token_file) {
645 | // check if it exists
646 | if ($this->Connection===false) {
647 | // Get cURL resource
648 | $this->Connection = curl_init();
649 |
650 | // set URL
651 | if($this->api_server_controller===false) { $url = $this->api_url.$this->api_app_id."/"; }
652 | else { $url = $this->api_url.$this->api_app_id.str_replace("//", "/", "/".$this->api_server_controller."/".$this->api_server_identifiers."/"); }
653 |
654 | // set default curl options and params
655 | curl_setopt_array($this->Connection, array(
656 | CURLOPT_RETURNTRANSFER => 1,
657 | CURLOPT_URL => $url,
658 | CURLOPT_HEADER => 0,
659 | CURLOPT_VERBOSE => $this->debug,
660 | CURLOPT_TIMEOUT => 30,
661 | CURLOPT_HTTPHEADER => array("Content-Type: application/json"),
662 | CURLOPT_USERAGENT => 'phpipam-api php class',
663 | // ssl
664 | CURLOPT_SSL_VERIFYHOST => false,
665 | CURLOPT_SSL_VERIFYPEER => false,
666 | // save headers
667 | CURLINFO_HEADER_OUT => true
668 | )
669 | );
670 | }
671 | }
672 |
673 | /**
674 | * Adds params to request if required
675 | *
676 | * @access private
677 | * @param mixed $params
678 | * @return void
679 | */
680 | private function curl_set_params ($params) {
681 | // params set ?
682 | if (is_array($params) && !$this->api_encrypt ) {
683 | if (sizeof($params)>0) {
684 | if ($this->api_server_method === 'GET')
685 | curl_setopt($this->Connection, CURLOPT_URL, $this->api_url.$this->api_app_id.str_replace("//", "/", "/".$this->api_server_controller."/".$this->api_server_identifiers."/?".http_build_query($params)));
686 | else
687 | curl_setopt($this->Connection, CURLOPT_POSTFIELDS, json_encode($params));
688 | }
689 | }
690 | // encrypt
691 | elseif ($this->api_encrypt) {
692 | // empty
693 | if(!is_array($params)) $params = array();
694 | if(!is_array($this->api_server_identifiers)) $this->api_server_identifiers = array();
695 |
696 | // join identifiers and parameters
697 | $params = array_merge($this->api_server_identifiers, $params);
698 | $params['controller'] = $this->api_server_controller;
699 |
700 | // create encrypted request
701 | $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
702 | $iv = openssl_random_pseudo_bytes($ivlen);
703 | $encrypted_request = base64_encode(openssl_encrypt(json_encode($params),$cipher,$this->api_key,$options=OPENSSL_RAW_DATA, $iv));
704 |
705 | // escape +
706 | $encrypted_request = urlencode($encrypted_request);
707 |
708 | // reset url
709 | curl_setopt($this->Connection, CURLOPT_URL, $this->api_url."?app_id=".$this->api_app_id."&enc_request=".$encrypted_request);
710 | }
711 | }
712 |
713 | /**
714 | * Sets HTTP method to use for queries
715 | *
716 | * @access private
717 | * @return void
718 | */
719 | private function curl_set_http_method () {
720 | curl_setopt($this->Connection, CURLOPT_CUSTOMREQUEST, $this->api_server_method);
721 | }
722 |
723 | /**
724 | * Adds token to http header
725 | *
726 | * @access private
727 | * @param mixed $token_file
728 | * @return void
729 | */
730 | private function curl_add_token_header ($token_file) {
731 | if($token_file!==false) {
732 | // open file and save token
733 | $token = @file($token_file);
734 | // save token
735 | if(isset($token[0])) {
736 | $this->token = trim($token[0]);
737 | $this->token_expires = trim($token[1]);
738 |
739 | // is token still valid ?
740 | if (strlen($this->token)<2 && $this->token_expires < time()) {
741 | // initiate authentication
742 | $this->curl_authenticate ();
743 | //save token to file
744 | $this->write_token_file ($token_file);
745 | }
746 | }
747 | else {
748 | $this->curl_authenticate ();
749 | //save token to file
750 | $this->write_token_file ($token_file);
751 |
752 | }
753 | }
754 | // token not saved, try to retrieve it
755 | else {
756 | $this->curl_authenticate ();
757 | }
758 |
759 | // add token to headers
760 | $this->curl_add_http_header ("token", $this->token);
761 | }
762 |
763 | /**
764 | * Adds http headers
765 | *
766 | * @access private
767 | * @param mixed $name
768 | * @param mixed $value
769 | * @return void
770 | */
771 | private function curl_add_http_header ($name, $value) {
772 | $headers = array(
773 | "Content-Type: application/json",
774 | "$name: $value"
775 | );
776 | // save
777 | curl_setopt($this->Connection, CURLOPT_HTTPHEADER, $headers);
778 | }
779 |
780 | /**
781 | * Writes token to token file
782 | *
783 | * @access private
784 | * @param mixed $filename
785 | * @return void
786 | */
787 | private function write_token_file ($filename) {
788 | //save token
789 | try {
790 | $myfile = fopen($filename, "w");
791 | fwrite($myfile, $this->token);
792 | fwrite($myfile, "\n");
793 | fwrite($myfile, $this->token_expires);
794 | // close file
795 | fclose($myfile);
796 | }
797 | catch ( Exception $e ) {
798 | $this->exception("Cannot write file $filename");
799 | }
800 | }
801 |
802 | /**
803 | * Removes token file if expired / invalid
804 | *
805 | * @access private
806 | * @param mixed $token_file
807 | * @return void
808 | */
809 | private function delete_token_file ($token_file) {
810 | //save token
811 | try {
812 | $myfile = fopen($token_file, "w");
813 | fwrite($myfile, "");
814 | // close file
815 | fclose($myfile);
816 | }
817 | catch ( Exception $e ) {
818 | $this->exception("Cannot write file $token_file");
819 | }
820 | }
821 |
822 | /**
823 | * Executes request.
824 | *
825 | * @access private
826 | * @return void
827 | */
828 | private function curl_execute () {
829 | // send request and save response
830 | $resp = curl_exec($this->Connection);
831 |
832 | // curl error check
833 | if (curl_errno($this->Connection)) {
834 | $this->exception("Curl error: ".curl_error($this->Connection));
835 | }
836 | else {
837 | // return result object
838 | return json_decode($resp);
839 | }
840 | }
841 |
842 | /**
843 | * Store result code
844 | *
845 | * @method curl_save_result_code
846 | * @return void
847 | */
848 | private function curl_save_headers () {
849 | // save result and result code
850 | $this->response_headers = curl_getinfo($this->Connection);
851 | }
852 |
853 | /**
854 | * send authenticate request and save token if provided, otherwise throw error.
855 | *
856 | * @access private
857 | * @return void
858 | */
859 | private function curl_authenticate () {
860 | // Get cURL resource
861 | $c_auth = curl_init();
862 |
863 | // set default curl options and params
864 | curl_setopt_array($c_auth, array(
865 | CURLOPT_RETURNTRANSFER => 1,
866 | CURLOPT_URL => $this->api_url.$this->api_app_id."/user/",
867 | CURLOPT_HEADER => 0,
868 | CURLOPT_VERBOSE => $this->debug,
869 | CURLOPT_TIMEOUT => 30,
870 | CURLOPT_USERAGENT => 'phpipam-api php class',
871 | // ssl
872 | CURLOPT_SSL_VERIFYHOST => 0,
873 | CURLOPT_SSL_VERIFYPEER => 0,
874 | CURLOPT_POST => true,
875 | CURLOPT_HTTPHEADER => array(
876 | 'Content-Length: 0',
877 | 'Authorization: Basic '. base64_encode($this->api_username.":".$this->api_password)
878 | )
879 | )
880 | );
881 | // send request and save response
882 | $resp = curl_exec($c_auth);
883 |
884 | // curl error check
885 | if (curl_errno($c_auth)) {
886 | $this->exception("Curl error: ".curl_error($c_auth));
887 | }
888 | else {
889 | // return result object
890 | $auth_resp = json_decode($resp);
891 | // ok ?
892 | if ($auth_resp->code == 200) {
893 | if (isset($auth_resp->data->token)) {
894 | // save token
895 | $this->token = $auth_resp->data->token;
896 | $this->token_expires = strtotime($auth_resp->data->expires);
897 | }
898 | else {
899 | $this->exception("Cannot obtain access token");
900 | }
901 | }
902 | // error
903 | else {
904 | // save response
905 | $this->result = $auth_resp;
906 | }
907 | }
908 | }
909 |
910 | }
911 |
912 |
913 | ?>
914 |
--------------------------------------------------------------------------------
/php-client/example.php:
--------------------------------------------------------------------------------
1 | set_debug (true);
18 | # execute - result is stored to $API->result, save it to own array if multiple calls needed after execute
19 | $API->execute ("GET", "addresses", array("first_free", "7"), array(), $token_file);
20 | # get result
21 | $result = $API->get_result();
22 |
23 | /**
24 | * Some examples
25 | *
26 | * Delete, POST examples
27 | * $API->execute ("DELETE", "subnets", array(7, "permissions"), array(), $token_file);
28 | * $API->execute ("POST", "vrf", array(), array("number"=>"114","name"=>"API"), $token_file);
29 | *
30 | * Get headers in array
31 | * $response_headers = $API->response_headers ();
32 | */
33 |
34 | # print result
35 | print_r($response_headers);
36 | print_r(json_decode($result, true));
37 | ?>
38 |
--------------------------------------------------------------------------------