Skip to content

Commit 123f9b0

Browse files
committed
PHPC-1498: Read auto encryption options from driverOptions
1 parent a19fdb0 commit 123f9b0

File tree

6 files changed

+238
-2
lines changed

6 files changed

+238
-2
lines changed

php_phongo.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2720,6 +2720,129 @@ static mongoc_client_t* php_phongo_find_client(const char* hash, size_t hash_len
27202720
return NULL;
27212721
}
27222722

2723+
#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
2724+
static bool phongo_manager_set_auto_encryption_opts(php_phongo_manager_t* manager, zval* driverOptions TSRMLS_DC) /* {{{ */
2725+
{
2726+
zval* zAutoEncryptionOpts;
2727+
bson_error_t error = { 0 };
2728+
mongoc_auto_encryption_opts_t* auto_encryption_opts = NULL;
2729+
bool retval = false;
2730+
2731+
if (!driverOptions || !php_array_existsc(driverOptions, "autoEncryption")) {
2732+
return true;
2733+
}
2734+
2735+
zAutoEncryptionOpts = php_array_fetch(driverOptions, "autoEncryption");
2736+
2737+
if (Z_TYPE_P(zAutoEncryptionOpts) != IS_ARRAY) {
2738+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"autoEncryption\" driver option to be array, %s given", PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(zAutoEncryptionOpts));
2739+
return false;
2740+
}
2741+
2742+
auto_encryption_opts = mongoc_auto_encryption_opts_new();
2743+
2744+
if (php_array_existsc(zAutoEncryptionOpts, "keyVaultClient")) {
2745+
zval* key_vault_client = php_array_fetch(zAutoEncryptionOpts, "keyVaultClient");
2746+
2747+
if (Z_TYPE_P(key_vault_client) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(key_vault_client), php_phongo_manager_ce TSRMLS_CC)) {
2748+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"keyVaultClient\" encryption option to be %s, %s given", ZSTR_VAL(php_phongo_manager_ce->name), PHONGO_ZVAL_CLASS_OR_TYPE_NAME_P(key_vault_client));
2749+
goto cleanup;
2750+
}
2751+
2752+
mongoc_auto_encryption_opts_set_keyvault_client(auto_encryption_opts, Z_MANAGER_OBJ_P(key_vault_client)->client);
2753+
}
2754+
2755+
if (php_array_existsc(zAutoEncryptionOpts, "keyVaultNamespace")) {
2756+
char* key_vault_ns;
2757+
char* db_name;
2758+
char* coll_name;
2759+
int plen;
2760+
zend_bool pfree;
2761+
2762+
key_vault_ns = php_array_fetch_string(zAutoEncryptionOpts, "keyVaultNamespace", &plen, &pfree);
2763+
2764+
if (!phongo_split_namespace(key_vault_ns, &db_name, &coll_name)) {
2765+
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Expected \"keyVaultNamespace\" encryption option to contain a full collection name");
2766+
2767+
if (pfree) {
2768+
str_efree(key_vault_ns);
2769+
}
2770+
2771+
goto cleanup;
2772+
}
2773+
2774+
mongoc_auto_encryption_opts_set_keyvault_namespace(auto_encryption_opts, db_name, coll_name);
2775+
2776+
efree(db_name);
2777+
efree(coll_name);
2778+
2779+
if (pfree) {
2780+
str_efree(key_vault_ns);
2781+
}
2782+
}
2783+
2784+
if (php_array_existsc(zAutoEncryptionOpts, "kmsProviders")) {
2785+
zval* kms_providers = php_array_fetch(zAutoEncryptionOpts, "kmsProviders");
2786+
bson_t bson_providers = BSON_INITIALIZER;
2787+
2788+
php_phongo_zval_to_bson(kms_providers, PHONGO_BSON_NONE, &bson_providers, NULL TSRMLS_CC);
2789+
if (EG(exception)) {
2790+
goto cleanup;
2791+
}
2792+
2793+
mongoc_auto_encryption_opts_set_kms_providers(auto_encryption_opts, &bson_providers);
2794+
2795+
bson_destroy(&bson_providers);
2796+
}
2797+
2798+
if (php_array_existsc(zAutoEncryptionOpts, "schemaMap")) {
2799+
zval* schema_map = php_array_fetch(zAutoEncryptionOpts, "schemaMap");
2800+
bson_t bson_map = BSON_INITIALIZER;
2801+
2802+
php_phongo_zval_to_bson(schema_map, PHONGO_BSON_NONE, &bson_map, NULL TSRMLS_CC);
2803+
if (EG(exception)) {
2804+
goto cleanup;
2805+
}
2806+
2807+
mongoc_auto_encryption_opts_set_schema_map(auto_encryption_opts, &bson_map);
2808+
2809+
bson_destroy(&bson_map);
2810+
}
2811+
2812+
if (php_array_existsc(zAutoEncryptionOpts, "bypassAutoEncryption")) {
2813+
zend_bool bypass_auto_encryption = php_array_fetch_bool(zAutoEncryptionOpts, "bypassAutoEncryption");
2814+
2815+
mongoc_auto_encryption_opts_set_bypass_auto_encryption(auto_encryption_opts, bypass_auto_encryption);
2816+
}
2817+
2818+
if (php_array_existsc(zAutoEncryptionOpts, "extraOptions")) {
2819+
zval* extra_options = php_array_fetch(zAutoEncryptionOpts, "extraOptions");
2820+
bson_t bson_options = BSON_INITIALIZER;
2821+
2822+
php_phongo_zval_to_bson(extra_options, PHONGO_BSON_NONE, &bson_options, NULL TSRMLS_CC);
2823+
if (EG(exception)) {
2824+
goto cleanup;
2825+
}
2826+
2827+
mongoc_auto_encryption_opts_set_extra(auto_encryption_opts, &bson_options);
2828+
2829+
bson_destroy(&bson_options);
2830+
}
2831+
2832+
if (!mongoc_client_enable_auto_encryption(manager->client, auto_encryption_opts, &error)) {
2833+
phongo_throw_exception_from_bson_error_t(&error TSRMLS_CC);
2834+
goto cleanup;
2835+
}
2836+
2837+
retval = true;
2838+
2839+
cleanup:
2840+
mongoc_auto_encryption_opts_destroy(auto_encryption_opts);
2841+
return retval;
2842+
}
2843+
/* }}} */
2844+
#endif
2845+
27232846
void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string, zval* options, zval* driverOptions TSRMLS_DC) /* {{{ */
27242847
{
27252848
bson_t bson_options = BSON_INITIALIZER;
@@ -2798,6 +2921,13 @@ void phongo_manager_init(php_phongo_manager_t* manager, const char* uri_string,
27982921
}
27992922
#endif
28002923

2924+
#ifdef MONGOC_ENABLE_CLIENT_SIDE_ENCRYPTION
2925+
if (!phongo_manager_set_auto_encryption_opts(manager, driverOptions TSRMLS_CC)) {
2926+
/* Exception should already have been thrown */
2927+
goto cleanup;
2928+
}
2929+
#endif
2930+
28012931
MONGOC_DEBUG("Created client hash: %s\n", manager->client_hash);
28022932
php_phongo_persist_client(manager->client_hash, manager->client_hash_len, manager->client TSRMLS_CC);
28032933

src/LIBMONGOCRYPT_VERSION_CURRENT

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.1-dev+20191220git5ff8a05d97
1+
1.0.1-dev+20200108gitb6cab3967e
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
MongoDB\Driver\Manager::__construct(): auto encryption options
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_libmongocrypt(); ?>
6+
--FILE--
7+
<?php
8+
9+
$baseOptions = [
10+
'keyVaultNamespace' => 'admin.dataKeys',
11+
'kmsProviders' => ['aws' => (object) ['accessKeyId' => 'abc', 'secretAccessKey' => 'def']]
12+
];
13+
14+
$tests = [
15+
[],
16+
['keyVaultClient' => new MongoDB\Driver\Manager()],
17+
['schemaMap' => [
18+
'default.default' => [
19+
'properties' => [
20+
'encrypted_objectId' => [
21+
'encrypt' => [
22+
'keyId' => [
23+
[
24+
'$binary' => [
25+
'base64' => 'AAAAAAAAAAAAAAAAAAAAAA==',
26+
'subType' => '04',
27+
],
28+
],
29+
],
30+
'bsonType' => 'objectId',
31+
'algorithm' => 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic',
32+
],
33+
],
34+
],
35+
'bsonType' => 'object',
36+
],
37+
]],
38+
['bypassAutoEncryption' => true],
39+
['extraOptions' => ['mongocryptdBypassSpawn' => true]],
40+
];
41+
42+
foreach ($tests as $autoEncryptionOptions) {
43+
$manager = new MongoDB\Driver\Manager(null, [], ['autoEncryption' => $autoEncryptionOptions + $baseOptions]);
44+
}
45+
46+
?>
47+
===DONE===
48+
<?php exit(0); ?>
49+
--EXPECT--
50+
===DONE===
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
MongoDB\Driver\Manager::__construct(): incomplete auto encryption options
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
5+
<?php skip_if_not_libmongocrypt(); ?>
6+
--FILE--
7+
<?php
8+
9+
require_once __DIR__ . '/../utils/tools.php';
10+
11+
$tests = [
12+
[],
13+
['keyVaultNamespace' => 'admin.keys'],
14+
];
15+
16+
foreach ($tests as $driverOptions) {
17+
echo throws(function() use ($driverOptions) {
18+
$manager = new MongoDB\Driver\Manager(null, [], ['autoEncryption' => $driverOptions]);
19+
}, 'MongoDB\Driver\Exception\RuntimeException'), "\n\n";
20+
}
21+
22+
?>
23+
===DONE===
24+
<?php exit(0); ?>
25+
--EXPECT--
26+
OK: Got MongoDB\Driver\Exception\RuntimeException
27+
Key vault namespace option required
28+
29+
OK: Got MongoDB\Driver\Exception\RuntimeException
30+
KMS providers option required
31+
32+
===DONE===

tests/utils/skipif.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,30 @@ function skip_if_not_libmongoc_ssl(array $libs = [])
355355
}
356356
}
357357

358+
/**
359+
* Skips the test if the driver was not compiled with support for FLE
360+
*/
361+
function skip_if_not_libmongocrypt()
362+
{
363+
$lib = get_module_info('libmongocrypt');
364+
365+
if ($lib === 'disabled') {
366+
exit('skip libmongocrypt is not enabled');
367+
}
368+
}
369+
370+
/**
371+
* Skips the test if the driver was compiled with support for FLE
372+
*/
373+
function skip_if_libmongocrypt()
374+
{
375+
$lib = get_module_info('libmongocrypt');
376+
377+
if ($lib !== 'disabled') {
378+
exit('skip libmongocrypt is enabled');
379+
}
380+
}
381+
358382
/**
359383
* Skips the test if the collection cannot be dropped.
360384
*

0 commit comments

Comments
 (0)