Merge pull request #25303 from HannahShiSFB/psm-security

PHP: support for PSM security
pull/25396/head
Stanley Cheung 4 years ago committed by GitHub
commit ff028754cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/php/bin/run_gen_code_test.sh
  2. 47
      src/php/ext/grpc/channel_credentials.c
  3. 26
      src/php/tests/generated_code/AbstractGeneratedCodeTest.php
  4. 5
      src/php/tests/generated_code/GeneratedCodeTest.php
  5. 4
      src/php/tests/generated_code/GeneratedCodeWithCallbackTest.php
  6. 7
      src/php/tests/generated_code/math_server.js
  7. 2
      src/php/tests/unit_tests/ChannelCredentialsTest.php
  8. 256
      src/php/tests/unit_tests/ChannelTest.php

@ -17,6 +17,8 @@ set -e
cd $(dirname $0) cd $(dirname $0)
source ./determine_extension_dir.sh source ./determine_extension_dir.sh
export GRPC_TEST_HOST=localhost:50051 export GRPC_TEST_HOST=localhost:50051
export GRPC_TEST_INSECURE_HOST=localhost:50052
php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \
../tests/generated_code/GeneratedCodeTest.php ../tests/generated_code/GeneratedCodeTest.php
php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \ php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \

@ -233,7 +233,46 @@ PHP_METHOD(ChannelCredentials, createComposite) {
* @return null * @return null
*/ */
PHP_METHOD(ChannelCredentials, createInsecure) { PHP_METHOD(ChannelCredentials, createInsecure) {
RETURN_NULL(); grpc_channel_credentials* creds = grpc_insecure_credentials_create();
zval* creds_object = grpc_php_wrap_channel_credentials(
creds, strdup("INSECURE"), false TSRMLS_CC);
RETURN_DESTROY_ZVAL(creds_object);
}
/**
* Create XDS channel credentials
* @param ChannelCredentials $fallback_creds The fallback credentials used
* if the channel target does not have the 'xds:///' scheme or if the xDS
* control plane does not provide information on how to fetch credentials
* dynamically.
* @return ChannelCredentials The xDS channel credentials object
*/
PHP_METHOD(ChannelCredentials, createXds) {
grpc_channel_credentials* xds_creds = NULL;
zval* fallback_creds = NULL;
if (zend_parse_parameters_ex(0, // ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "O", &fallback_creds,
grpc_ce_channel_credentials) != SUCCESS) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"createXds expects a fallback credentials",
1 TSRMLS_CC);
return;
}
wrapped_grpc_channel_credentials* wrapped_fallback_creds =
PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel_credentials,
fallback_creds);
xds_creds = grpc_xds_credentials_create(wrapped_fallback_creds->wrapped);
const char* fallback_creds_hash_str =
wrapped_fallback_creds->hashstr ? wrapped_fallback_creds->hashstr : "";
// prefix "XDS:" as the hash of the xDS channel
char* hash_str = malloc(strlen(fallback_creds_hash_str) + strlen("XDS:") + 1);
strcpy(hash_str, "XDS:");
strcat(hash_str, fallback_creds_hash_str);
zval* xds_creds_obj = grpc_php_wrap_channel_credentials(
xds_creds, hash_str, false /* has_call_creds */ TSRMLS_CC);
RETURN_DESTROY_ZVAL(xds_creds_obj);
} }
ZEND_BEGIN_ARG_INFO_EX(arginfo_setDefaultRootsPem, 0, 0, 1) ZEND_BEGIN_ARG_INFO_EX(arginfo_setDefaultRootsPem, 0, 0, 1)
@ -263,6 +302,10 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_createInsecure, 0, 0, 0) ZEND_BEGIN_ARG_INFO_EX(arginfo_createInsecure, 0, 0, 0)
ZEND_END_ARG_INFO() ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_createXds, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, fallback_creds, Grpc\\ChannelCredentials, 1)
ZEND_END_ARG_INFO()
static zend_function_entry channel_credentials_methods[] = { static zend_function_entry channel_credentials_methods[] = {
PHP_ME(ChannelCredentials, setDefaultRootsPem, arginfo_setDefaultRootsPem, PHP_ME(ChannelCredentials, setDefaultRootsPem, arginfo_setDefaultRootsPem,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
@ -278,6 +321,8 @@ static zend_function_entry channel_credentials_methods[] = {
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(ChannelCredentials, createInsecure, arginfo_createInsecure, PHP_ME(ChannelCredentials, createInsecure, arginfo_createInsecure,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(ChannelCredentials, createXds, arginfo_createXds,
ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_FE_END PHP_FE_END
}; };

@ -134,29 +134,33 @@ abstract class AbstractGeneratedCodeTest extends \PHPUnit\Framework\TestCase
public function testCallCredentialsCallback() public function testCallCredentialsCallback()
{ {
$div_arg = new Math\DivArgs(); $div_arg = new Math\DivArgs();
$div_arg->setDividend(7);
$div_arg->setDivisor(4);
$call = self::$client->Div($div_arg, array(), array( $call = self::$client->Div($div_arg, array(), array(
'call_credentials_callback' => function ($context) { 'call_credentials_callback' => function ($context) {
return array(); return array();
}, },
)); ));
$call->cancel();
list($response, $status) = $call->wait(); list($response, $status) = $call->wait();
$this->assertSame(\Grpc\STATUS_CANCELLED, $status->code); $this->assertSame(\Grpc\STATUS_OK, $status->code);
} }
public function testCallCredentialsCallback2() public function testInsecureChannelCallCredentialsCallback()
{ {
$div_arg = new Math\DivArgs(); $div_arg = new Math\DivArgs();
$call = self::$client->Div($div_arg); $div_arg->setDividend(7);
$call_credentials = Grpc\CallCredentials::createFromPlugin( $div_arg->setDivisor(4);
function ($context) { $client = new Math\MathClient(
getenv('GRPC_TEST_INSECURE_HOST'), [
'credentials' => Grpc\ChannelCredentials::createInsecure(),
]);
$call = $client->Div($div_arg, array(), array(
'call_credentials_callback' => function ($context) {
return array(); return array();
} },
); ));
$call->setCallCredentials($call_credentials);
$call->cancel();
list($response, $status) = $call->wait(); list($response, $status) = $call->wait();
$this->assertSame(\Grpc\STATUS_CANCELLED, $status->code); $this->assertSame(\Grpc\STATUS_UNAUTHENTICATED, $status->code);
} }
public function testInvalidMethodName() public function testInvalidMethodName()

@ -24,7 +24,10 @@ class GeneratedCodeTest extends AbstractGeneratedCodeTest
{ {
self::$client = new Math\MathClient( self::$client = new Math\MathClient(
getenv('GRPC_TEST_HOST'), [ getenv('GRPC_TEST_HOST'), [
'credentials' => Grpc\ChannelCredentials::createInsecure(), 'credentials' => Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__).'/../data/ca.pem')),
'grpc.ssl_target_name_override' => 'foo.test.google.fr',
]); ]);
} }

@ -24,7 +24,9 @@ class GeneratedCodeWithCallbackTest extends AbstractGeneratedCodeTest
{ {
self::$client = new Math\MathClient( self::$client = new Math\MathClient(
getenv('GRPC_TEST_HOST'), getenv('GRPC_TEST_HOST'),
['credentials' => Grpc\ChannelCredentials::createInsecure(), ['credentials' => Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__).'/../data/ca.pem')),
'grpc.ssl_target_name_override' => 'foo.test.google.fr',
'update_metadata' => function ($a_hash, 'update_metadata' => function ($a_hash,
$client = []) { $client = []) {
$a_copy = $a_hash; $a_copy = $a_hash;

@ -120,7 +120,12 @@ function main() {
Sum: Sum, Sum: Sum,
DivMany: DivMany, DivMany: DivMany,
}); });
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); server.bind('0.0.0.0:50052', grpc.ServerCredentials.createInsecure());
var fs = require('fs');
var key_data = fs.readFileSync(__dirname + '/../data/server1.key');
var pem_data = fs.readFileSync(__dirname + '/../data/server1.pem');
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createSsl(null, [{private_key: key_data,
cert_chain: pem_data}]));
server.start(); server.start();
} }

@ -43,7 +43,7 @@ class ChanellCredentialsTest extends \PHPUnit\Framework\TestCase
public function testCreateInsecure() public function testCreateInsecure()
{ {
$channel_credentials = Grpc\ChannelCredentials::createInsecure(); $channel_credentials = Grpc\ChannelCredentials::createInsecure();
$this->assertNull($channel_credentials); $this->assertNotNull($channel_credentials);
} }
public function testDefaultRootsPem() public function testDefaultRootsPem()

@ -44,6 +44,31 @@ class ChannelTest extends \PHPUnit\Framework\TestCase
$this->assertNotNull($channel); $this->assertNotNull($channel);
} }
public function testCreateXdsWithSsl()
{
$xdsCreds = \Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createSsl()
);
$this->assertNotNull($xdsCreds);
}
public function testCreateXdsWithInsecure() {
$xdsCreds = \Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createInsecure()
);
$this->assertNotNull($xdsCreds);
}
public function testCreateXdsWithNull() {
$this->expectException(\InvalidArgumentException::class);
$xdsCreds = \Grpc\ChannelCredentials::createXds(null);
}
public function testCreateXdsWithInvalidType() {
$this->expectException(\TypeError::class);
$xdsCreds = \Grpc\ChannelCredentials::createXds("invalid-type");
}
public function testGetConnectivityState() public function testGetConnectivityState()
{ {
$this->channel = new Grpc\Channel('localhost:50001', $this->channel = new Grpc\Channel('localhost:50001',
@ -275,17 +300,90 @@ class ChannelTest extends \PHPUnit\Framework\TestCase
$this->channel2->close(); $this->channel2->close();
} }
public function testPersistentChannelSameChannelCredentials() public function persistentChannelSameChannelCredentialsProvider(): array
{ {
$creds1 = Grpc\ChannelCredentials::createSsl(); return [
$creds2 = Grpc\ChannelCredentials::createSsl(); [
Grpc\ChannelCredentials::createSsl(),
$this->channel1 = new Grpc\Channel('localhost:50019', Grpc\ChannelCredentials::createSsl(),
["credentials" => $creds1, 50301,
"grpc_target_persist_bound" => 3, ],
]); [
$this->channel2 = new Grpc\Channel('localhost:50019', Grpc\ChannelCredentials::createSsl(
["credentials" => $creds2]); file_get_contents(dirname(__FILE__) . '/../data/ca.pem')
),
Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__) . '/../data/ca.pem')
),
50302,
],
[
Grpc\ChannelCredentials::createInSecure(),
Grpc\ChannelCredentials::createInSecure(),
50303,
],
[
\Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createSsl()
),
\Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createSsl()
),
50304,
],
[
\Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createSsl()
),
\Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createSsl()
),
50305,
],
[
\Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__) . '/../data/ca.pem')
)
),
\Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__) . '/../data/ca.pem')
)
),
50306,
],
[
\Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createInSecure()
),
\Grpc\ChannelCredentials::createXds(
\Grpc\ChannelCredentials::createInSecure()
),
50307,
],
];
}
/**
* @dataProvider persistentChannelSameChannelCredentialsProvider
*/
public function testPersistentChannelSameChannelCredentials(
$creds1,
$creds2,
$port
) {
$this->channel1 = new Grpc\Channel(
'localhost:' . $port,
[
"credentials" => $creds1,
"grpc_target_persist_bound" => 3,
]
);
$this->channel2 = new Grpc\Channel(
'localhost:' . $port,
["credentials" => $creds2]
);
// try to connect on channel1 // try to connect on channel1
$state = $this->channel1->getConnectivityState(true); $state = $this->channel1->getConnectivityState(true);
@ -300,70 +398,78 @@ class ChannelTest extends \PHPUnit\Framework\TestCase
$this->channel2->close(); $this->channel2->close();
} }
public function testPersistentChannelDifferentChannelCredentials() public function persistentChannelDifferentChannelCredentialsProvider(): array
{ {
$creds1 = Grpc\ChannelCredentials::createSsl(); return [
$creds2 = Grpc\ChannelCredentials::createSsl( [
file_get_contents(dirname(__FILE__).'/../data/ca.pem')); Grpc\ChannelCredentials::createSsl(),
Grpc\ChannelCredentials::createSsl(
$this->channel1 = new Grpc\Channel('localhost:50020', file_get_contents(dirname(__FILE__) . '/../data/ca.pem')
["credentials" => $creds1, ),
"grpc_target_persist_bound" => 3, 50351,
]); ],
$this->channel2 = new Grpc\Channel('localhost:50020', [
["credentials" => $creds2]); Grpc\ChannelCredentials::createSsl(),
Grpc\ChannelCredentials::createInsecure(),
// try to connect on channel1 50352,
$state = $this->channel1->getConnectivityState(true); ],
$this->waitUntilNotIdle($this->channel1); [
\Grpc\ChannelCredentials::createXds(
$state = $this->channel1->getConnectivityState(); \Grpc\ChannelCredentials::createSsl()
$this->assertConnecting($state); ),
$state = $this->channel2->getConnectivityState(); \Grpc\ChannelCredentials::createXds(
$this->assertEquals(GRPC\CHANNEL_IDLE, $state); \Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__) . '/../data/ca.pem')
$this->channel1->close(); )
$this->channel2->close(); ),
} 50353,
],
public function testPersistentChannelSameChannelCredentialsRootCerts() [
{ \Grpc\ChannelCredentials::createXds(
$creds1 = Grpc\ChannelCredentials::createSsl( \Grpc\ChannelCredentials::createSsl()
file_get_contents(dirname(__FILE__).'/../data/ca.pem')); ),
$creds2 = Grpc\ChannelCredentials::createSsl( \Grpc\ChannelCredentials::createXds(
file_get_contents(dirname(__FILE__).'/../data/ca.pem')); \Grpc\ChannelCredentials::createInsecure()
),
$this->channel1 = new Grpc\Channel('localhost:50021', 50354,
["credentials" => $creds1, ],
"grpc_target_persist_bound" => 3, [
]); \Grpc\ChannelCredentials::createInsecure(),
$this->channel2 = new Grpc\Channel('localhost:50021', \Grpc\ChannelCredentials::createXds(
["credentials" => $creds2]); \Grpc\ChannelCredentials::createInsecure()
),
// try to connect on channel1 50355,
$state = $this->channel1->getConnectivityState(true); ],
$this->waitUntilNotIdle($this->channel1); [
\Grpc\ChannelCredentials::createSsl(),
$state = $this->channel1->getConnectivityState(); \Grpc\ChannelCredentials::createXds(
$this->assertConnecting($state); \Grpc\ChannelCredentials::createSsl()
$state = $this->channel2->getConnectivityState(); ),
$this->assertConnecting($state); 50356,
],
$this->channel1->close(); ];
$this->channel2->close(); }
}
/**
public function testPersistentChannelDifferentSecureChannelCredentials() * @dataProvider persistentChannelDifferentChannelCredentialsProvider
{ */
$creds1 = Grpc\ChannelCredentials::createSsl(); public function testPersistentChannelDifferentChannelCredentials(
$creds2 = Grpc\ChannelCredentials::createInsecure(); $creds1,
$creds2,
$this->channel1 = new Grpc\Channel('localhost:50022', $port
["credentials" => $creds1, ) {
"grpc_target_persist_bound" => 3,
]); $this->channel1 = new Grpc\Channel(
$this->channel2 = new Grpc\Channel('localhost:50022', 'localhost:' . $port,
["credentials" => $creds2]); [
"credentials" => $creds1,
"grpc_target_persist_bound" => 3,
]
);
$this->channel2 = new Grpc\Channel(
'localhost:' . $port,
["credentials" => $creds2]
);
// try to connect on channel1 // try to connect on channel1
$state = $this->channel1->getConnectivityState(true); $state = $this->channel1->getConnectivityState(true);

Loading…
Cancel
Save