Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow http options to be passed into ParseClient #513

Merged
merged 8 commits into from
May 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Parse/HttpClients/ParseCurlHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,18 @@ public function setCAFile($caFile)
$this->parseCurl->setOption(CURLOPT_CAINFO, $caFile);
}

/**
* Sets multiple curl options
* https://www.php.net/manual/en/function.curl-setopt.php
*
* @param array $options Array of options to set
* @throws ParseException
*/
public function setHttpOptions($options)
{
$this->parseCurl->setOptionsArray($options);
}

/**
* Gets the error code
*
Expand Down
7 changes: 7 additions & 0 deletions src/Parse/HttpClients/ParseHttpable.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ public function setTimeout($timeout);
*/
public function setCAFile($caFile);

/**
* Sets http options to pass to the http client
*
* @param string $httpOptions Options to set
*/
public function setHttpOptions($httpOptions);

/**
* Gets the error code
*
Expand Down
25 changes: 25 additions & 0 deletions src/Parse/HttpClients/ParseStreamHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ class ParseStreamHttpClient implements ParseHttpable
*/
private $caFile;

/**
* Options to pass to the stream context.
*
* @var array
*/
private $httpOptions;

/**
* Optional timeout for this request
*
Expand Down Expand Up @@ -195,6 +202,12 @@ public function send($url, $method = 'GET', $data = array())
$this->options['ssl']['cafile'] = $this->caFile;
}

if (isset($this->httpOptions)) {
foreach ($this->httpOptions as $key => $value) {
$this->options[$key] = $value;
}
}

// add additional options for this request
$this->options['http'] = array(
'method' => $method,
Expand Down Expand Up @@ -264,6 +277,7 @@ public function send($url, $method = 'GET', $data = array())

// clear options
$this->options = array();
$this->httpOptions = array();

// flush our existing headers
$this->headers = array();
Expand Down Expand Up @@ -348,6 +362,17 @@ public function setCAFile($caFile)
$this->caFile = $caFile;
}

/**
* Sets http options to pass to the stream context
* https://www.php.net/manual/en/context.php
*
* @param array $httpOptions options to set
*/
public function setHttpOptions($httpOptions)
{
$this->httpOptions = $httpOptions;
}

/**
* Sets the request timeout
*
Expand Down
25 changes: 25 additions & 0 deletions src/Parse/ParseClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ final class ParseClient
*/
private static $caFile;

/**
* Options to pass to the http client.
*
* @var array
*/
private static $httpOptions;

/**
* Constant for version string to include with requests.
*
Expand Down Expand Up @@ -301,6 +308,21 @@ public static function setCAFile($caFile)
self::$caFile = $caFile;
}

/**
* Sets http options to pass to the http client
* For curl
* https://www.php.net/manual/en/function.curl-setopt.php
*
* For stream context
* https://www.php.net/manual/en/context.php
*
* @param array $httpOptions options to set
*/
public static function setHttpOptions($httpOptions)
{
self::$httpOptions = $httpOptions;
}

/**
* ParseClient::_encode, internal method for encoding object values.
*
Expand Down Expand Up @@ -452,6 +474,9 @@ private static function getPreparedHttpClient()
// set CA file
$httpClient->setCAFile(self::$caFile);
}
if (isset(self::$httpOptions)) {
$httpClient->setHttpOptions(self::$httpOptions);
}

return $httpClient;
}
Expand Down
6 changes: 6 additions & 0 deletions tests/Parse/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,10 @@ public static function print($text)
{
fwrite(STDOUT, $text . "\n");
}

public static function printArray($array)
{
print_r($array);
ob_end_flush();
}
}
53 changes: 53 additions & 0 deletions tests/Parse/ParseClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

use PHPUnit\Framework\TestCase;

defined('CURLOPT_PINNEDPUBLICKEY') || define('CURLOPT_PINNEDPUBLICKEY', 10230);

class ParseClientTest extends TestCase
{
public static function setUpBeforeClass() : void
Expand All @@ -35,6 +37,9 @@ public function tearDown() : void

// unset CA file
ParseClient::setCAFile(null);

// unset http options
ParseClient::setHttpOptions(null);
}

/**
Expand Down Expand Up @@ -667,4 +672,52 @@ public function testCheckBadServer()
$this->assertTrue(isset($health['error_message']));
}
}

/**
* @group test-http-options
*/
public function testCurlHttpOptions()
{
if (function_exists('curl_init')) {
ParseClient::setHttpClient(new ParseCurlHttpClient());
ParseClient::setServerURL('https://localhost:1338', 'parse');
ParseClient::setHttpOptions([
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_PINNEDPUBLICKEY => 'sha256//Oz+R70/uIv0irdBWc7RNPyCGeZNbN+CBiPLjJxXWigg=',
CURLOPT_SSLCERT => dirname(__DIR__).'/keys/client.crt',
CURLOPT_SSLKEY => dirname(__DIR__).'/keys/client.key',
]);
$health = ParseClient::getServerHealth();

$this->assertNotNull($health);
$this->assertEquals($health['status'], 200);
$this->assertEquals($health['response']['status'], 'ok');
Helper::setServerURL();
}
}

/**
* @group test-http-options
*/
public function testStreamHttpOptions()
{
ParseClient::setHttpClient(new ParseStreamHttpClient());
ParseClient::setServerURL('https://localhost:1338', 'parse');
ParseClient::setHttpOptions([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
'local_cert' => dirname(__DIR__).'/keys/client.crt',
'local_pk' => dirname(__DIR__).'/keys/client.key',
'peer_fingerprint' => '29F36676EFA0CA18B5B571C6144580044CB289C2',
]
]);
$health = ParseClient::getServerHealth();

$this->assertNotNull($health);
$this->assertEquals($health['status'], 200);
$this->assertEquals($health['response']['status'], 'ok');
Helper::setServerURL();
}
}
75 changes: 75 additions & 0 deletions tests/gencerts.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/bin/bash
# https://gist.github.com/ryankurte/bc0d8cff6e73a6bb1950
# https://curl.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html
# ./gencerts.sh parseca localhost parsephp keys/
# ./gencerts.sh parseca client parsephp keys/

set -e

if [ "$#" -ne 3 ] && [ "$#" -ne 4 ]; then
echo "Usage: $0 CA NAME ORG"
echo "CA - name of fake CA"
echo "NAME - name of fake client"
echo "ORG - organisation for both"
echo "[DIR] - directory for cert output"
exit
fi

CA=$1
NAME=$2
ORG=$3

if [ -z "$4" ]; then
DIR=./
else
DIR=$4
fi

if [ ! -d "$DIR" ]; then
mkdir -p $DIR
fi

LENGTH=4096
DAYS=1000

SUBJECT=/C=NZ/ST=AKL/L=Auckland/O=$ORG

if [ ! -f "$DIR/$CA.key" ]; then

echo Generating CA
openssl genrsa -out $DIR/$CA.key $LENGTH

echo Signing CA
openssl req -x509 -new -nodes -key $DIR/$CA.key -sha256 -days 1024 -out $DIR/$CA.crt -subj $SUBJECT/CN=$CA

openssl x509 -in $DIR/$CA.crt -out $DIR/$CA.pem -text
openssl x509 -sha1 -noout -in $DIR/$CA.pem -fingerprint | sed 's/SHA1 Fingerprint=//g' >> $DIR/$CA.fp

else
echo Located existing CA
fi

if [ ! -f "$DIR/$NAME.key" ]; then

echo Generating keys
openssl genrsa -out $DIR/$NAME.key $LENGTH

echo Generating CSR
openssl req -new -out $DIR/$NAME.csr -key $DIR/$NAME.key -subj $SUBJECT/CN=$NAME

echo Signing cert
openssl x509 -req -days $DAYS -in $DIR/$NAME.csr -out $DIR/$NAME.crt -CA $DIR/$CA.crt -CAkey $DIR/$CA.key -CAcreateserial

echo Generating PEM
openssl x509 -in $DIR/$NAME.crt -out $DIR/$NAME.pem -text

openssl x509 -sha1 -noout -in $DIR/$NAME.pem -fingerprint | sed 's/SHA1 Fingerprint=//g' > $DIR/$NAME.fp

echo Cleaning Up
rm $DIR/*.csr

else
echo Located existing client certificate
fi

echo Done
30 changes: 30 additions & 0 deletions tests/keys/client.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFITCCAwkCCQDEwoQengRnzDANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJO
WjEMMAoGA1UECAwDQUtMMREwDwYDVQQHDAhBdWNrbGFuZDERMA8GA1UECgwIcGFy
c2VwaHAxEDAOBgNVBAMMB3BhcnNlY2EwHhcNMjMwNTEyMjA0MzAzWhcNMjYwMjA1
MjA0MzAzWjBSMQswCQYDVQQGEwJOWjEMMAoGA1UECAwDQUtMMREwDwYDVQQHDAhB
dWNrbGFuZDERMA8GA1UECgwIcGFyc2VwaHAxDzANBgNVBAMMBmNsaWVudDCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMlKDLogZSNxm5S4h97XM8A1+MsP
RaK15g8ebVEP7OGrwX1bvLVis0U/ixwHs0mqjQ9tbuefMZyiRgdds+8tpRCCuqGo
dwSk8YMmOlrF5xIpBT2cXJLhGvDyY0F0RLFZYBoioTYFth4i91DkzhmBaL6vjyB7
dXduR1JQbzTpQHkhofPziQsNtinf8qBqLbH1dFaqwUUEgtsKJyaPlxJR21TF3Fv+
2K/fmoyzP6Er7eUSCvJRRH1hCwzHxl7GqTKyQeaS1RLdrHYqZmSeiJpxwl8uSdBs
x4y8wG4lhRdantCCANlTwLd7zPiuIu+RBP276o2+02K8my9N2STZUgHXefSoNx4M
alYujKBUV+2qmhR9H2HlUB/C/h5Sb8PSlfWyD/bo3+agyw/1+9rfMUYCmiEtdik7
amoBaahoqAHL8S3K19L0ytWkgFejSMzn+i4VDifnwupXHifDL7CPDX0vevFNDvC7
HMLkBWmkNaTduDL5P3ximtIXE7akhK+ufiNoO3KLItenCENxCzUdNdDHguei2U5E
vhTyaTmIIrkUGxQ+aVDXRF2njAeQNMdTjsCAiiSN1corYX8RXvNo8QZQUEaHG42u
O6Yolsw8EZotbpExo1jbiDlI2pVIuwJdtaDCucPN/X6uZ8odGQ0LUeyTBYda/1OG
VIQzPZnxSHzqPzuZAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAHOLgs6FLIv+Vvpx
fNtwabgOI2JxkFwaAujwWJS10tmczJp9qZilOlVBBhDFRBwBKqAaanHKCYkEfP6u
dgC8RMOOYOb0gk6Tj3+zhvM4Qz+n8Cn2fA2+EtFXTKyMfJHuG/zddTLep2Phh9c9
t5s/8aHAuqM9RGiA66V7mJiR9G5E8cNpyHniCh8Z11kABPMzAy92LyEGUlRwCrWx
fCwItnzY2/7J8IW20rPIpb0EWmYHhxkUUzu7APQgvJpAUTdhmVKb9GLCUyY+oICE
1WrnV9OQiqYVGFQkry9FXyKbsLVM6b6ar8DIXpYTYnd11sqFdiUUo4oItYYrO/1O
0Bt0PX6hWYjR4r7ZT23KWAHZdlU4EFfrLJeZ6HDeYttJF68x9s8RZGgVU9Xlb/7X
KGRVyCWI7aWzvI1lBVAnc7b7B9LrIkdHnYDt/ettmRvI/zZRBh73T7EPOQB7bEzP
M8BXfAr/+qa2ToBWNd9AJrw7rg+OWGD801iXqsREyLr15nRIR12mGdKuyMkfghk1
9J1Sd0fkfB2ci7Rn3afRdKksGuADQ2fvYihw0lALOPzSq/FYRqZBzwv9Qmw43CKd
euEPcCfT7VYY47lmfFfKBcVv8d7NiJZRGkIUYUxS/UAsrLiBCgRkaUACcbLok7sJ
jrdaTDx4EZu93dmJbEozNO6dRiLb
-----END CERTIFICATE-----
Binary file added tests/keys/client.der
Binary file not shown.
1 change: 1 addition & 0 deletions tests/keys/client.fp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
D7:10:BE:24:E6:85:A2:F8:79:F8:36:EF:42:A0:EC:B3:EC:93:C2:FB
51 changes: 51 additions & 0 deletions tests/keys/client.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
Loading