Skip to content

PHPLIB-1702: Always consult server encryptedFieldsMap when dropping collections with autoEncryption enabled #1745

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

Merged
merged 4 commits into from
Aug 13, 2025
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ public function drop(array $options = [])

if (! isset($options['encryptedFields'])) {
$options['encryptedFields'] = get_encrypted_fields_from_driver($this->databaseName, $this->collectionName, $this->manager)
?? get_encrypted_fields_from_server($this->databaseName, $this->collectionName, $this->manager, $server);
?? get_encrypted_fields_from_server($this->databaseName, $this->collectionName, $server);
}

$operation = isset($options['encryptedFields'])
Expand Down
2 changes: 1 addition & 1 deletion src/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ public function dropCollection(string $collectionName, array $options = [])

if (! isset($options['encryptedFields'])) {
$options['encryptedFields'] = get_encrypted_fields_from_driver($this->databaseName, $collectionName, $this->manager)
?? get_encrypted_fields_from_server($this->databaseName, $collectionName, $this->manager, $server);
?? get_encrypted_fields_from_server($this->databaseName, $collectionName, $server);
}

$operation = isset($options['encryptedFields'])
Expand Down
7 changes: 1 addition & 6 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,8 @@ function get_encrypted_fields_from_driver(string $databaseName, string $collecti
* @see Database::dropCollection()
* @return array|object|null
*/
function get_encrypted_fields_from_server(string $databaseName, string $collectionName, Manager $manager, Server $server)
function get_encrypted_fields_from_server(string $databaseName, string $collectionName, Server $server)
{
// No-op if the encryptedFieldsMap autoEncryption driver option was omitted
if ($manager->getEncryptedFieldsMap() === null) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, it seems like we'd want the Manager to be able to report whether autoEncryption is enabled.

return null;
}

$collectionInfoIterator = (new ListCollections($databaseName, ['filter' => ['name' => $collectionName]]))->execute($server);

foreach ($collectionInfoIterator as $collectionInfo) {
Expand Down
93 changes: 93 additions & 0 deletions tests/Functions/GetEncryptedFieldsFromServerFunctionalTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace MongoDB\Tests\Functions;

use MongoDB\BSON\Binary;
use MongoDB\Collection;
use MongoDB\Database;
use MongoDB\Driver\ClientEncryption;
use MongoDB\Driver\WriteConcern;
use MongoDB\Tests\FunctionalTestCase;

use function iterator_count;
use function str_repeat;

class GetEncryptedFieldsFromServerFunctionalTest extends FunctionalTestCase
{
private ClientEncryption $clientEncryption;
private Collection $keyVaultCollection;
private Database $database;

public function setUp(): void
{
parent::setUp();

$this->skipIfClientSideEncryptionIsNotSupported();

if ($this->isStandalone()) {
$this->markTestSkipped('Queryable encryption requires replica sets');
}

$this->skipIfServerVersion('<', '7.0.0', 'Queryable encryption requires MongoDB 7.0 or later');

$client = static::createTestClient();

// Ensure the key vault collection is dropped before each test
$this->keyVaultCollection = $client->getCollection('keyvault', 'datakeys', ['writeConcern' => new WriteConcern(WriteConcern::MAJORITY)]);
$this->keyVaultCollection->drop();

$this->clientEncryption = $client->createClientEncryption([
'keyVaultNamespace' => $this->keyVaultCollection->getNamespace(),
'kmsProviders' => ['local' => ['key' => new Binary(str_repeat("\0", 96)) ]],
]);

$this->database = $client->getDatabase($this->getDatabaseName());
}

public function tearDown(): void
{
$this->keyVaultCollection->drop();
}

/** @see https://jira.mongodb.org/browse/PHPLIB-1702 */
public function testDatabaseDropCollectionConsultsEncryptedFieldsFromServer(): void
{
$originalNumCollections = iterator_count($this->database->listCollectionNames());

$this->database->createEncryptedCollection(
$this->getCollectionName(),
$this->clientEncryption,
'local',
null,
['encryptedFields' => ['fields' => []]],
);

// createEncryptedCollection should create three collections
$this->assertCount($originalNumCollections + 3, $this->database->listCollectionNames());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the collection already exists before running the test, this assertion fails.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this only a concern when aborting the test locally (or retrying after a failure)?

No objections to dropping it before this first assertion.


$this->database->dropCollection($this->getCollectionName());

$this->assertCount($originalNumCollections, $this->database->listCollectionNames());
}

/** @see https://jira.mongodb.org/browse/PHPLIB-1702 */
public function testCollectionDropConsultsEncryptedFieldsFromServer(): void
{
$originalNumCollections = iterator_count($this->database->listCollectionNames());

$this->database->createEncryptedCollection(
$this->getCollectionName(),
$this->clientEncryption,
'local',
null,
['encryptedFields' => ['fields' => []]],
);

// createEncryptedCollection should create three collections
$this->assertCount($originalNumCollections + 3, $this->database->listCollectionNames());

$this->database->getCollection($this->getCollectionName())->drop();

$this->assertCount($originalNumCollections, $this->database->listCollectionNames());
}
}
2 changes: 1 addition & 1 deletion tests/drivers-evergreen-tools
Loading