Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving Curl client ssl to Guzzle

Tags:

php

curl

ssl

guzzle

I'm using Guzzle v3.9.2 with both php 5.3 and php 5.5.

I have the following working curl code that uses an ssl client certificate:

$url = "https://example.com/";
$cert_file = '/path/to/certificate.pem';

$ch = curl_init();
$options = array(
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_URL => $url ,
  CURLOPT_SSLCERT => $cert_file ,
);

curl_setopt_array($ch , $options);
$output = curl_exec($ch);

if (!$output) {
  echo "Curl Error : " . curl_error($ch);
}
else {
  echo htmlentities($output);
}

I have tried to move it to Guzzle:

require '/var/www/vendor/autoload.php';
use Guzzle\Http\Client;
$client = new Client();
$request = $client->get($url, array('cert' => $cert_file));
$response = $client->send($request);
echo $response . PHP_EOL;
print 'HI' . PHP_EOL;

When I run it using curl I get a 200 response. When I use Guzzle I get a 403.

like image 999
greggles Avatar asked Sep 18 '14 23:09

greggles


1 Answers

If you are using private key then you have to use ssl_key option it will not 
work with cert.You can use **cert** options only with client certificate.

This error occurs because of three reason.

  1. Correct certificate path is not provided. Hence not able to read & pass the certificate information to server.
  2. The server failed to authenticate the request because of invalid certificate.
  3. Php curl is not able to read the certificate file because of file owner/permission issue.

How Guzzle set ssl curl path:

  • Guzzle use CURLOPT_CAINFO for file & CURLOPT_CAPATH for multiple certificates in directory
  • Default certificate path is vendor/Http/Resources/cacert.pem.
  • If you don't use phar in require_once then you can replace existing certificate file with your new certificate because it initialize SSL on every request. This will work without changing the code.
  • Guzzle uses ssl.certificate_authority parameter to set the curl ssl certification. It supports values as false,true or file path
  • You can set the file path while class initialization as below-

    $cert_file = '/var/www/stack/25924147/cert/example.pem'; #Use absolute path as relative path will not work
    $client = new Client();
    $client->setDefaultOption('verify',true); #pass it for self-signed certificate
    $client->setSslVerification($cert_file,true,2);  #Last Verify Option states default value is 2. When the verify value is 0, the connection succeeds regardless of the names in the certificate. Use that ability with caution!. When the verify value is 1, curl_easy_setopt will return an error
    try{
        $request = $client->get($url);
        $options = $request->getCurlOptions(); #used to check curl options is set properly.
        var_dump($options); 
        $response = $client->send($request);
        echo $response . PHP_EOL;
        print 'HI' . PHP_EOL;
    }catch( Guzzle\Http\Exception\CurlException $e){
        print_r($e->getResponse());
        echo "\n Curl Error \n";
    }catch(Guzzle\Http\Exception\ClientErrorResponseException $e){
       print_r($e->getResponse());
       echo "\n Response Error \n";
    }catch( Guzzle\Http\Exception\RequestException $e){
      print_r($e->getResponse());
      echo "\n REquest Error \n";
    }
    

OR If you wants to pass certificate on every request try below code

   $cert_file = '/var/www/stack/25924147/cert/example.pem'; #Use absolute path as relative path will not work
   $client = new Client();
   $request = $client->get('https://www.example.com', array(), array(

      'ssl_key' => array('/etc/pki/private_key.pem')

  )


With Passoword - 
 $request = $client->get('https://www.example.com', array(), array(

     'ssl_key' => array('/etc/pki/private_key.pem', 's3cr3tp455w0rd')

 )

For Guzzle Http client Doc check - The Guzzle HTTP client

like image 177
Rajesh Ujade Avatar answered Oct 14 '22 00:10

Rajesh Ujade