Skip to content

Commit b4bfd0e

Browse files
committed
Code review feedback
Demonstrates schema validation errors in example scripts Relocates local schema section after server-side schema, and clarifies that it should be used in conjunction with server-side schemas (not instead of). Revise comments and variable names in scripts and update expected output for tests accordingly.
1 parent 29db0f8 commit b4bfd0e

10 files changed

+260
-219
lines changed

docs/examples/create_data_key.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,24 @@
1111
// Generate a secure local key to use for this script
1212
$localKey = new Binary(random_bytes(96));
1313

14-
/* Create a client with no encryption options. Additionally, create a
15-
* ClientEncryption object to manage data keys. */
14+
// Create a client with no encryption options
1615
$client = new Client($uri);
1716

17+
// Create a ClientEncryption object to manage data encryption keys
1818
$clientEncryption = $client->createClientEncryption([
1919
'keyVaultNamespace' => 'encryption.__keyVault',
2020
'kmsProviders' => [
2121
'local' => ['key' => $localKey],
2222
],
2323
]);
2424

25-
/* Drop the key vault collection and create an encryption key. This would
26-
* typically be done during application deployment. To store the key ID for
27-
* later use, you can use serialize() or var_export(). */
25+
/* Create a new key vault collection for this script. The application must also
26+
* ensure that a unique index exists for keyAltNames. */
2827
$client->selectCollection('encryption', '__keyVault')->drop();
28+
$client->selectCollection('encryption', '__keyVault')->createIndex(['keyAltNames' => 1], ['unique' => true]);
29+
30+
/* Create a data encryption key. To store the key ID for later use, you can use
31+
* serialize(), var_export(), etc. */
2932
$keyId = $clientEncryption->createDataKey('local');
3033

3134
print_r($keyId);

docs/examples/csfle-automatic_encryption-local_schema.php

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use MongoDB\BSON\Binary;
44
use MongoDB\Client;
55
use MongoDB\Driver\ClientEncryption;
6+
use MongoDB\Driver\Exception\ServerException;
67

78
require __DIR__ . '/../../vendor/autoload.php';
89

@@ -11,62 +12,75 @@
1112
// Generate a secure local key to use for this script
1213
$localKey = new Binary(random_bytes(96));
1314

14-
/* Create a client with no encryption options. Additionally, create a
15-
* ClientEncryption object to manage data keys. */
15+
// Create a client with no encryption options
1616
$client = new Client($uri);
1717

18+
// Create a ClientEncryption object to manage data encryption keys
1819
$clientEncryption = $client->createClientEncryption([
1920
'keyVaultNamespace' => 'encryption.__keyVault',
2021
'kmsProviders' => [
2122
'local' => ['key' => $localKey],
2223
],
2324
]);
2425

25-
/* Drop the key vault collection and create an encryption key. Alternatively,
26-
* this key ID could be read from a configuration file. */
26+
/* Create a new key vault collection and data encryption key for this script.
27+
* Alternatively, this key ID could be read from a configuration file. */
2728
$client->selectCollection('encryption', '__keyVault')->drop();
29+
$client->selectCollection('encryption', '__keyVault')->createIndex(['keyAltNames' => 1], ['unique' => true]);
2830
$keyId = $clientEncryption->createDataKey('local');
2931

30-
/* Create a client with automatic encryption enabled. Specify a schemaMap option
31-
* to enforce a local JSON schema. */
32+
/* Define a JSON schema for the encrypted collection. Since this only utilizes
33+
* encryption schema syntax, it can be used for both the server-side and local
34+
* schema. */
35+
$schema = [
36+
'bsonType' => 'object',
37+
'properties' => [
38+
'encryptedField' => [
39+
'encrypt' => [
40+
'keyId' => [$keyId],
41+
'bsonType' => 'string',
42+
'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
43+
],
44+
],
45+
],
46+
];
47+
48+
/* Create another client with automatic encryption enabled. Configure a local
49+
* schema for the encrypted collection using the "schemaMap" option. */
3250
$encryptedClient = new Client($uri, [], [
3351
'autoEncryption' => [
3452
'keyVaultNamespace' => 'encryption.__keyVault',
3553
'kmsProviders' => ['local' => ['key' => $localKey]],
36-
'schemaMap' => [
37-
'test.coll' => [
38-
'bsonType' => 'object',
39-
'properties' => [
40-
'encryptedField' => [
41-
'encrypt' => [
42-
'keyId' => [$keyId],
43-
'bsonType' => 'string',
44-
'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
45-
],
46-
],
47-
],
48-
],
49-
],
54+
'schemaMap' => ['test.coll' => $schema],
5055
],
5156
]);
5257

53-
// Drop and create the collection.
58+
/* Create a new collection for this script. Configure a server-side schema by
59+
* explicitly creating the collection with a "validator" option.
60+
*
61+
* Note: without a server-side schema, another client could potentially insert
62+
* unencrypted data into the collection. Therefore, a local schema should always
63+
* be used in conjunction with a server-side schema. */
5464
$encryptedClient->selectDatabase('test')->dropCollection('coll');
55-
$encryptedClient->selectDatabase('test')->createCollection('coll');
65+
$encryptedClient->selectDatabase('test')->createCollection('coll', ['validator' => ['$jsonSchema' => $schema]]);
5666
$encryptedCollection = $encryptedClient->selectCollection('test', 'coll');
5767

58-
/* Using the encrypted client, insert and find a document. The encrypted field
59-
* will be automatically encrypted and decrypted. */
60-
$encryptedCollection->insertOne([
61-
'_id' => 1,
62-
'encryptedField' => 'mySecret',
63-
]);
68+
/* Using the encrypted client, insert and find a document to demonstrate that
69+
* the encrypted field is automatically encrypted and decrypted. */
70+
$encryptedCollection->insertOne(['_id' => 1, 'encryptedField' => 'mySecret']);
6471

6572
print_r($encryptedCollection->findOne(['_id' => 1]));
6673

6774
/* Using the client configured without encryption, find the same document and
68-
* observe that the field is not automatically decrypted. Additionally, the JSON
69-
* schema will prohibit inserting a document with an unencrypted field value. */
75+
* observe that the field is not automatically decrypted. */
7076
$unencryptedCollection = $client->selectCollection('test', 'coll');
7177

7278
print_r($unencryptedCollection->findOne(['_id' => 1]));
79+
80+
/* Attempt to insert another document with an unencrypted field value to
81+
* demonstrate that the server-side schema is enforced. */
82+
try {
83+
$unencryptedCollection->insertOne(['_id' => 2, 'encryptedField' => 'myOtherSecret']);
84+
} catch (ServerException $e) {
85+
printf("Error inserting document: %s\n", $e->getMessage());
86+
}

docs/examples/csfle-automatic_encryption-server_side_schema.php

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use MongoDB\BSON\Binary;
44
use MongoDB\Client;
55
use MongoDB\Driver\ClientEncryption;
6+
use MongoDB\Driver\Exception\ServerException;
67

78
require __DIR__ . '/../../vendor/autoload.php';
89

@@ -11,63 +12,67 @@
1112
// Generate a secure local key to use for this script
1213
$localKey = new Binary(random_bytes(96));
1314

14-
/* Create a client with no encryption options. Additionally, create a
15-
* ClientEncryption object to manage data keys. */
15+
// Create a client with no encryption options
1616
$client = new Client($uri);
1717

18+
// Create a ClientEncryption object to manage data encryption keys
1819
$clientEncryption = $client->createClientEncryption([
1920
'keyVaultNamespace' => 'encryption.__keyVault',
2021
'kmsProviders' => [
2122
'local' => ['key' => $localKey],
2223
],
2324
]);
2425

25-
/* Drop the key vault collection and create an encryption key. Alternatively,
26-
* this key ID could be read from a configuration file. */
26+
/* Create a new key vault collection and data encryption key for this script.
27+
* Alternatively, this key ID could be read from a configuration file. */
2728
$client->selectCollection('encryption', '__keyVault')->drop();
29+
$client->selectCollection('encryption', '__keyVault')->createIndex(['keyAltNames' => 1], ['unique' => true]);
2830
$keyId = $clientEncryption->createDataKey('local');
2931

30-
// Create a client with automatic encryption enabled
32+
// Create another client with automatic encryption enabled
3133
$encryptedClient = new Client($uri, [], [
3234
'autoEncryption' => [
3335
'keyVaultNamespace' => 'encryption.__keyVault',
3436
'kmsProviders' => ['local' => ['key' => $localKey]],
3537
],
3638
]);
3739

38-
/* Drop and create the collection. Specify a validator option when creating the
39-
* collection to enforce a server-side JSON schema. */
40-
$validator = [
41-
'$jsonSchema' => [
42-
'bsonType' => 'object',
43-
'properties' => [
44-
'encryptedField' => [
45-
'encrypt' => [
46-
'keyId' => [$keyId],
47-
'bsonType' => 'string',
48-
'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
49-
],
40+
// Define a JSON schema for the encrypted collection
41+
$schema = [
42+
'bsonType' => 'object',
43+
'properties' => [
44+
'encryptedField' => [
45+
'encrypt' => [
46+
'keyId' => [$keyId],
47+
'bsonType' => 'string',
48+
'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
5049
],
5150
],
5251
],
5352
];
5453

54+
/* Create a new collection for this script. Configure a server-side schema by
55+
* explicitly creating the collection with a "validator" option. */
5556
$encryptedClient->selectDatabase('test')->dropCollection('coll');
56-
$encryptedClient->selectDatabase('test')->createCollection('coll', ['validator' => $validator]);
57+
$encryptedClient->selectDatabase('test')->createCollection('coll', ['validator' => ['$jsonSchema' => $schema]]);
5758
$encryptedCollection = $encryptedClient->selectCollection('test', 'coll');
5859

59-
/* Using the encrypted client, insert and find a document. The encrypted field
60-
* will be automatically encrypted and decrypted. */
61-
$encryptedCollection->insertOne([
62-
'_id' => 1,
63-
'encryptedField' => 'mySecret',
64-
]);
60+
/* Using the encrypted client, insert and find a document to demonstrate that
61+
* the encrypted field is automatically encrypted and decrypted. */
62+
$encryptedCollection->insertOne(['_id' => 1, 'encryptedField' => 'mySecret']);
6563

6664
print_r($encryptedCollection->findOne(['_id' => 1]));
6765

6866
/* Using the client configured without encryption, find the same document and
69-
* observe that the field is not automatically decrypted. Additionally, the JSON
70-
* schema will prohibit inserting a document with an unencrypted field value. */
67+
* observe that the field is not automatically decrypted. */
7168
$unencryptedCollection = $client->selectCollection('test', 'coll');
7269

7370
print_r($unencryptedCollection->findOne(['_id' => 1]));
71+
72+
/* Attempt to insert another document with an unencrypted field value to
73+
* demonstrate that the server-side schema is enforced. */
74+
try {
75+
$unencryptedCollection->insertOne(['_id' => 2, 'encryptedField' => 'myOtherSecret']);
76+
} catch (ServerException $e) {
77+
printf("Error inserting document: %s\n", $e->getMessage());
78+
}

docs/examples/csfle-explicit_encryption.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,24 @@
1111
// Generate a secure local key to use for this script
1212
$localKey = new Binary(random_bytes(96));
1313

14-
/* Create a client with no encryption options. Additionally, create a
15-
* ClientEncryption object to manage data keys. */
14+
// Create a client with no encryption options
1615
$client = new Client($uri);
1716

17+
// Create a ClientEncryption object to manage data encryption keys
1818
$clientEncryption = $client->createClientEncryption([
1919
'keyVaultNamespace' => 'encryption.__keyVault',
2020
'kmsProviders' => [
2121
'local' => ['key' => $localKey],
2222
],
2323
]);
2424

25-
/* Drop the key vault collection and create an encryption key. Alternatively,
26-
* this key ID could be read from a configuration file. */
25+
/* Create a new key vault collection and data encryption key for this script.
26+
* Alternatively, this key ID could be read from a configuration file. */
2727
$client->selectCollection('encryption', '__keyVault')->drop();
28+
$client->selectCollection('encryption', '__keyVault')->createIndex(['keyAltNames' => 1], ['unique' => true]);
2829
$keyId = $clientEncryption->createDataKey('local');
2930

30-
// Select and drop a collection to use for this example
31+
// Create a new collection for this script
3132
$collection = $client->selectCollection('test', 'coll');
3233
$collection->drop();
3334

@@ -37,12 +38,13 @@
3738
'keyId' => $keyId,
3839
]);
3940

40-
$collection->insertOne(['encryptedField' => $encryptedValue]);
41+
$collection->insertOne(['_id' => 1, 'encryptedField' => $encryptedValue]);
4142

42-
/* Query for the document. The field will not be automatically decrypted
43-
* because the client was not configured with an autoEncryption driver option.
44-
* Manually decrypt the field value using the ClientEncryption object. */
43+
/* Using the client configured without encryption, find the document and observe
44+
* that the field is not automatically decrypted. */
4545
$document = $collection->findOne();
4646

47-
print_r($document->encryptedField);
48-
print_r($clientEncryption->decrypt($document->encryptedField));
47+
print_r($document);
48+
49+
// Manually decrypt the field
50+
printf("Decrypted: %s\n", $clientEncryption->decrypt($document->encryptedField));

docs/examples/csfle-explicit_encryption_automatic_decryption.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,21 @@
2020
],
2121
]);
2222

23-
// Create a ClientEncryption object to manage data keys
23+
// Create a ClientEncryption object to manage data encryption keys
2424
$clientEncryption = $client->createClientEncryption([
2525
'keyVaultNamespace' => 'encryption.__keyVault',
2626
'kmsProviders' => [
2727
'local' => ['key' => $localKey],
2828
],
2929
]);
3030

31-
/* Drop the key vault collection and create an encryption key. Alternatively,
32-
* this key ID could be read from a configuration file. */
31+
/* Create a new key vault collection and data encryption key for this script.
32+
* Alternatively, this key ID could be read from a configuration file. */
3333
$client->selectCollection('encryption', '__keyVault')->drop();
34+
$client->selectCollection('encryption', '__keyVault')->createIndex(['keyAltNames' => 1], ['unique' => true]);
3435
$keyId = $clientEncryption->createDataKey('local');
3536

36-
// Select and drop a collection to use for this example
37+
// Create a new collection for this script
3738
$collection = $client->selectCollection('test', 'coll');
3839
$collection->drop();
3940

@@ -43,10 +44,10 @@
4344
'keyId' => $keyId,
4445
]);
4546

46-
$collection->insertOne(['encryptedField' => $encryptedValue]);
47+
$collection->insertOne(['_id' => 1, 'encryptedField' => $encryptedValue]);
4748

48-
/* Query for the document. The field will still be automatically decrypted
49-
* because the client was configured with an autoEncryption driver option. */
49+
/* Using the client configured with encryption (but not automatic encryption),
50+
* find the document and observe that the field is automatically decrypted. */
5051
$document = $collection->findOne();
5152

52-
print_r($document->encryptedField);
53+
print_r($document);

docs/examples/key_alt_name.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use MongoDB\BSON\Binary;
44
use MongoDB\Client;
55
use MongoDB\Driver\ClientEncryption;
6+
use MongoDB\Driver\Exception\ServerException;
67

78
require __DIR__ . '/../../vendor/autoload.php';
89

@@ -11,23 +12,33 @@
1112
// Generate a secure local key to use for this script
1213
$localKey = new Binary(random_bytes(96));
1314

14-
/* Create a client with no encryption options. Additionally, create a
15-
* ClientEncryption object to manage data keys. */
15+
// Create a client with no encryption options
1616
$client = new Client($uri);
1717

18+
// Create a ClientEncryption object to manage data encryption keys
1819
$clientEncryption = $client->createClientEncryption([
1920
'keyVaultNamespace' => 'encryption.__keyVault',
2021
'kmsProviders' => [
2122
'local' => ['key' => $localKey],
2223
],
2324
]);
2425

25-
/* Drop the key vault collection and create an encryption key with an alternate
26-
* name. This would typically be done during application deployment. To store
27-
* the key ID for later use, you can use serialize() or var_export(). */
26+
/* Create a new key vault collection for this script. The application must also
27+
* ensure that a unique index exists for keyAltNames. */
2828
$client->selectCollection('encryption', '__keyVault')->drop();
29+
$client->selectCollection('encryption', '__keyVault')->createIndex(['keyAltNames' => 1], ['unique' => true]);
30+
31+
// Create a data encryption key with an alternate name
2932
$clientEncryption->createDataKey('local', ['keyAltNames' => ['myDataKey']]);
3033

34+
/* Attempt to create a second key with the same name to demonstrate that the
35+
* unique index is enforced. */
36+
try {
37+
$clientEncryption->createDataKey('local', ['keyAltNames' => ['myDataKey']]);
38+
} catch (ServerException $e) {
39+
printf("Error creating key: %s\n", $e->getMessage());
40+
}
41+
3142
// Encrypt a value, using the "keyAltName" option instead of "keyId"
3243
$encryptedValue = $clientEncryption->encrypt('mySecret', [
3344
'algorithm' => ClientEncryption::AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,

0 commit comments

Comments
 (0)