diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e8da644 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/vendor/ +/coverage/ + +composer.lock \ No newline at end of file diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 2803486..022d09f 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1 +1,2 @@ -Björn Roland \ No newline at end of file +Björn Roland +Tim Helfensdörfer \ No newline at end of file diff --git a/README.md b/README.md index a7d18ba..d8a558d 100644 --- a/README.md +++ b/README.md @@ -5,16 +5,13 @@ It's build upon the official API documentation at https://github.com/ssllabs/ssl ```PHP fetchApiInfo()); diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..a4d9e68 --- /dev/null +++ b/composer.json @@ -0,0 +1,28 @@ +{ + "name": "visualappeal/php-ssllabs-api", + "description": "API for ssllabs.com", + "type": "library", + "license": "GPL", + "authors": [ + { + "name": "Björn Roland", + "email": "bjoern.roland@gmail.com" + }, + { + "name": "Tim Helfensdörfer", + "email": "tim@visualappeal.de" + } + ], + "minimum-stability": "stable", + "require": { + "php": ">=7.0" + }, + "autoload": { + "psr-4": { + "": "src/" + } + }, + "require-dev": { + "phpunit/phpunit": "^7.4" + } +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..652c6d2 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,18 @@ + + + + ./tests + + + + + ./src + + + + + + \ No newline at end of file diff --git a/src/SslLabs.php b/src/SslLabs.php new file mode 100644 index 0000000..ea5f7a7 --- /dev/null +++ b/src/SslLabs.php @@ -0,0 +1,213 @@ +returnObjects = $returnObjects; + } + + /** + * Check SSL Labs availability + * + * API Call: info + * @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs-v3.md#check-ssl-labs-availability + * + * @return string|object + */ + public function info() + { + return $this->sendApiRequest('info'); + } + + /** + * Invoke assessment and check progress + * + * API Call: analyze + * @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs-v3.md#invoke-assessment-and-check-progress + * + * @param string $host Hostname to analyze + * @param bool $publish Publish results on ssllabs.com + * @param bool $startNew Force new report + * @param bool $fromCache Enable cache + * @param int $maxAge Cached age in hours + * @param string $all ("on"|"off"|"done") + * @param bool $ignoreMismatch Proceed even when the hostname and certificate doesn't match + * @return string|object + */ + public function analyze(string $host, bool $publish = false, bool $startNew = false, bool $fromCache = false, + int $maxAge = null, string $all = null, bool $ignoreMismatch = false) + { + return $this->sendApiRequest( + 'analyze', + [ + 'host' => $host, + 'publish' => $publish, + 'startNew' => $startNew, + 'fromCache' => $fromCache, + 'maxAge' => $maxAge, + 'all' => $all, + 'ignoreMismatch' => $ignoreMismatch, + ] + ); + } + + /** + * Same as analyze but prefer to receive cached information + * + * API Call: analyze + * + * @param string $host + * @param bool $publish + * @param int $maxAge + * @param string $all + * @param bool $ignoreMismatch + * @return string|object + */ + public function analyzeCached(string $host, bool $publish = false, int $maxAge = 24, string $all = 'done', bool $ignoreMismatch = false) + { + return $this->analyze($host, $publish, false, true, $maxAge, $all, $ignoreMismatch); + } + + /** + * Retrieve detailed endpoint information + * + * API Call: getEndpointData + * @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs-v3.md#retrieve-detailed-endpoint-information + * + * @param string $host + * @param string $s IP Address + * @param bool $fromCache Cached results + * @return string|object + */ + public function getEndpointData($host, $s, $fromCache = false) + { + $apiRequest = $this->sendApiRequest( + 'getEndpointData', + [ + 'host' => $host, + 's' => $s, + 'fromCache' => $fromCache, + ] + ); + + return $apiRequest; + } + + /** + * Retrieve known status codes + * + * API Call: getStatusCodes + * @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs-v3.md#retrieve-known-status-codes + * + * @return string|object + */ + public function getStatusCodes() + { + return $this->sendApiRequest('getStatusCodes'); + } + + /** + * Retrieve root certificates + * + * API Call: getRootCertsRaw + * @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs-v3.md#retrieve-root-certificates + * + * @return string|object + */ + public function getRootCertsRaw() + { + return $this->sendApiRequest('getRootCertsRaw'); + } + + /** + * Send API request + * + * @param string $apiCall + * @param array $parameters + * @return string|object JSON from API + */ + public function sendApiRequest(string $apiCall, array $parameters = []) + { + // We also want content from failed api responses + $context = stream_context_create( + [ + 'http' => [ + 'ignore_errors' => true + ], + ] + ); + + $url = self::API_URL . '/' . $apiCall . $this->buildGetParameterString($parameters); + + $apiResponse = file_get_contents( + $url, + false, + $context + ); + + if ($this->returnObjects === true) { + return json_decode($apiResponse); + } + + return $apiResponse; + } + + /** + * Set true to return all API responses as JSON object, false returns it as simple JSON strings + * + * @param bool $returnObjects + */ + public function setReturnJsonObjects(bool $returnObjects) + { + $this->returnObjects = $returnObjects; + } + + /** + * Getter for returnObjects + * + * @return bool true returns all API responses as JSON object, false returns it as simple JSON string + */ + public function getReturnJsonObjects() + { + return $this->returnObjects; + } + + /** + * Helper function to build get parameter string for URL + * + * @param array $parameters + * @return string + */ + private function buildGetParameterString(array $parameters) + { + $string = ''; + + $counter = 0; + foreach ($parameters as $name => $value) { + if (!is_string($name) || (!is_string($value) && !is_bool($value) && !is_int($value))) { + continue; + } + + if (is_bool($value)) { + $value = ($value) ? 'on' : 'off'; + } + + $string .= ($counter == 0) ? '?' : '&'; + $string .= urlencode($name) . '=' . urlencode($value); + + $counter++; + } + + return $string; + } +} \ No newline at end of file diff --git a/sslLabsApi.php b/sslLabsApi.php deleted file mode 100644 index 32f3d4e..0000000 --- a/sslLabsApi.php +++ /dev/null @@ -1,216 +0,0 @@ - - * @license GNU GENERAL PUBLIC LICENSE v3 - */ - -class sslLabsApi -{ - CONST API_URL = "https://api.ssllabs.com/api/v2"; - - private $returnJsonObjects; - - /** - * sslLabsApi::__construct() - */ - public function __construct($returnJsonObjects = false) - { - $this->returnJsonObjects = (boolean) $returnJsonObjects; - } - - /** - * sslLabsApi::fetchApiInfo() - * - * API Call: info - * @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md - */ - public function fetchApiInfo() - { - return ($this->sendApiRequest('info')); - } - - /** - * sslLabsApi::fetchHostInformation() - * - * API Call: analyze - * @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md - * - * @param string $host Hostname to analyze - * @param boolean $publish - * @param boolean $startNew - * @param boolean $fromCache - * @param int $maxAge - * @param string $all - * @param boolean $ignoreMismatch - */ - public function fetchHostInformation($host, $publish = false, $startNew = false, $fromCache = false, $maxAge = NULL, $all = NULL, $ignoreMismatch = false) - { - $apiRequest = $this->sendApiRequest - ( - 'analyze', - array - ( - 'host' => $host, - 'publish' => $publish, - 'startNew' => $startNew, - 'fromCache' => $fromCache, - 'maxAge' => $maxAge, - 'all' => $all, - 'ignoreMismatch' => $ignoreMismatch - ) - ); - - return ($apiRequest); - } - - /** - * sslLabsApi::fetchHostInformationCached() - * - * API Call: analyze - * Same as fetchHostInformation() but prefer to receive cached information - * - * @param string $host - * @param int $maxAge - * @param string $publish - * @param string $ignoreMismatch - */ - public function fetchHostInformationCached($host, $maxAge, $publish = false, $ignoreMismatch = false) - { - return($this->fetchHostInformation($host, $publish, false, true, $maxAge, 'done', $ignoreMismatch)); - } - - /** - * sslLabsApi::fetchEndpointData() - * - * API Call: getEndpointData - * @see https://github.com/ssllabs/ssllabs-scan/blob/master/ssllabs-api-docs.md - * - * @param string $host - * @param string $s - * @param string $fromCache - * @return string - */ - public function fetchEndpointData($host, $s, $fromCache = false) - { - $apiRequest = $this->sendApiRequest - ( - 'getEndpointData', - array - ( - 'host' => $host, - 's' => $s, - 'fromCache' => $fromCache - ) - ); - - return ($apiRequest); - } - - /** - * sslLabsApi::fetchStatusCodes() - * - * API Call: getStatusCodes - */ - public function fetchStatusCodes() - { - return ($this->sendApiRequest('getStatusCodes')); - } - - /** - * sslLabsApi::sendApiRequest() - * - * Send API request - * - * @param string $apiCall - * @param array $parameters - * @return string JSON from API - */ - public function sendApiRequest($apiCall, $parameters = array()) - { - //we also want content from failed api responses - $context = stream_context_create - ( - array - ( - 'http' => array - ( - 'ignore_errors' => true - ) - ) - ); - - $apiResponse = file_get_contents(self::API_URL . '/' . $apiCall . $this->buildGetParameterString($parameters), false, $context); - - if($this->returnJsonObjects) - { - return (json_decode($apiResponse)); - } - - return ($apiResponse); - } - - /** - * sslLabsApi::setReturnJsonObjects() - * - * Setter for returnJsonObjects - * Set true to return all API responses as JSON object, false returns it as simple JSON strings (default) - * - * @param boolean $returnJsonObjects - */ - public function setReturnJsonObjects($returnJsonObjects) - { - $this->returnJsonObjects = (boolean) $returnJsonObjects; - } - - /** - * sslLabsApi::getReturnJsonObjects() - * - * Getter for returnJsonObjects - * - * @return boolean true returns all API responses as JSON object, false returns it as simple JSON string - */ - public function getReturnJsonObjects() - { - return ($this->returnJsonObjects); - } - - /** - * sslLabsApi::buildGetParameterString() - * - * Helper function to build get parameter string for URL - * - * @param array $parameters - * @return string - */ - private function buildGetParameterString($parameters) - { - $string = ''; - - $counter = 0; - foreach($parameters as $name => $value) - { - if(!is_string($name) || (!is_string($value) && !is_bool($value) && !is_int($value))) - { - continue; - } - - if(is_bool($value)) - { - $value = ($value) ? 'on' : 'off'; - } - - $string .= ($counter == 0) ? '?' : '&'; - $string .= urlencode($name) . '=' . urlencode($value); - - $counter++; - } - - return ($string); - } -} \ No newline at end of file diff --git a/tests/SslLabsTest.php b/tests/SslLabsTest.php new file mode 100644 index 0000000..2672d9a --- /dev/null +++ b/tests/SslLabsTest.php @@ -0,0 +1,68 @@ +sslLabs = new SslLabs; + } + + public function testInfo(): void + { + $info = $this->sslLabs->info(); + $this->assertObjectHasAttribute('engineVersion', $info); + } + + public function testStringResponse(): void + { + $this->sslLabs = new SslLabs(false); + $info = $this->sslLabs->info(); + $this->assertInternalType('string', $info); + } + + public function testAnalyze(): void + { + $host = 'https://www.ssllabs.com'; + + $analyze = $this->sslLabs->analyze($host); + $this->assertObjectHasAttribute('host', $analyze); + $this->assertEquals($host, $analyze->host); + } + + public function testAnalyzeCached(): void + { + $host = 'https://www.ssllabs.com'; + + $analyze = $this->sslLabs->analyzeCached($host); + $this->assertObjectHasAttribute('host', $analyze); + $this->assertEquals($host, $analyze->host); + } + + public function testGetEndpointData(): void + { + $host = 'https://www.ssllabs.com'; + $ip = '64.41.200.100'; + + $endpointData = $this->sslLabs->getEndpointData($host, $ip); + $this->assertInternalType('object', $endpointData); + } + + public function testGetStatusCodes(): void + { + $statusCodes = $this->sslLabs->getStatusCodes(); + $this->assertInternalType('object', $statusCodes); + } + + public function testGetRootCertsRaw(): void + { + $rootCertsRaw = $this->sslLabs->getRootCertsRaw(); + $this->assertNull($rootCertsRaw); + } +}