Navigation Menu

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

CSHARP-4255: Fix bug and some tests. #993

Merged
merged 6 commits into from Jan 17, 2023

Conversation

DmitryLukyanov
Copy link

No description provided.

/// <param name="createCollectionOptions">The create collection options.</param>
/// <param name="kmsProvider">The kms provider.</param>
/// <param name="dataKeyOptions">The datakey options.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <remarks>
/// if EncryptionFields contains a keyId with a null value, a data key will be automatically generated and assigned to keyId value.
/// </remarks>
public void CreateEncryptedCollection<TCollection>(CollectionNamespace collectionNamespace, CreateCollectionOptions createCollectionOptions, string kmsProvider, DataKeyOptions dataKeyOptions, CancellationToken cancellationToken = default)
public void CreateEncryptedCollection(IMongoDatabase database, string collectionName, CreateCollectionOptions createCollectionOptions, string kmsProvider, DataKeyOptions dataKeyOptions, CancellationToken cancellationToken = default)
Copy link
Author

Choose a reason for hiding this comment

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

spec API is described here

@JamesKovacs JamesKovacs removed their request for review December 15, 2022 23:26
@@ -82,59 +82,59 @@ public ClientEncryption(ClientEncryptionOptions clientEncryptionOptions)
/// <summary>
/// Create encrypted collection.
/// </summary>
/// <param name="collectionNamespace">The collection namespace.</param>
/// <param name="database">The database.</param>
/// <param name="collectionName">The collectionName.</param>
Copy link
Contributor

Choose a reason for hiding this comment

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

the collection name

Copy link
Author

Choose a reason for hiding this comment

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

done

}

/// <summary>
/// Create encrypted collection.
/// </summary>
/// <param name="collectionNamespace">The collection namespace.</param>
/// <param name="database">The database.</param>
/// <param name="collectionName">The collectionName.</param>
Copy link
Contributor

Choose a reason for hiding this comment

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

the collection name

Copy link
Author

Choose a reason for hiding this comment

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

done

void AssertInvalidOperationException(Exception ex, string message) => ex.Should().BeOfType<InvalidOperationException>().Which.Message.Should().Be(message);
}

private class EncryptedFieldsComparer : IEqualityComparer<BsonDocument>
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: sealed.

Copy link
Author

Choose a reason for hiding this comment

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

done

bDocument["keyId"] = aDocument["keyId"];
}
});
public int GetHashCode(BsonDocument obj) => obj.GetHashCode();
Copy link
Contributor

Choose a reason for hiding this comment

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

blank line.

Copy link
Author

Choose a reason for hiding this comment

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

done

if (BsonDocument.TryParse(expectedResult, out var encryptedFields))
{
var createCollectionOptions = new CreateCollectionOptions() { EncryptedFields = encryptedFieldsStr != null ? BsonDocument.Parse(encryptedFieldsStr) : null };
subject.CreateEncryptedCollection(database, collectionName: collectionName, createCollectionOptions, kmsProvider: kmsProvider, dataKeyOptions);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's better to omit trivial parameter naming like:
collectionName: collectionName, and kmsProvider: kmsProvider. Here and elsewhere.

Copy link
Author

Choose a reason for hiding this comment

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

done

public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("_encryptedFields", _encryptedFields);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is nameof applicable here?

Copy link
Author

Choose a reason for hiding this comment

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

done

}
catch (Exception ex)
{
throw new MongoEncryptionCreateCollectionException(ex, encryptedFields);
Copy link
Contributor

Choose a reason for hiding this comment

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

Returning operation data, which is unrelated to exception, within exception is a bit unusual, but I am fine with this here.
@JamesKovacs this is follow up for our slack discussion, please double check that you are ok with this as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

Discussed with Dima via Slack. While from an API perspective it feels odd to return successfully-created keys in the exception, I don't see another reasonable way to avoid phantom encryption keys. While we could modify CreateCollectionOptions as we generate dataKeys, it violates the principle of least surprise to modify one's input parameters unexpectedly. I think this is the best option given the available trade-offs.

var createCollectionOptions = new CreateCollectionOptions() { EncryptedFields = encryptedFieldsStr != null ? BsonDocument.Parse(encryptedFieldsStr) : null };
AssertInvalidOperationException(Record.Exception(() => subject.CreateEncryptedCollection(database, collectionName, createCollectionOptions, kmsProvider, dataKeyOptions)), expectedResult);

createCollectionOptions = new CreateCollectionOptions() { EncryptedFields = encryptedFieldsStr != null ? BsonDocument.Parse(encryptedFieldsStr) : null };
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to recreate CreateCollectionOptions everywhere now.

Copy link
Author

Choose a reason for hiding this comment

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

done

effectiveEncryptedFields.EncryptedFields.WithComparer(new EncryptedFieldsComparer()).Should().Be(encryptedFields.DeepClone());

createCollectionOptions = new CreateCollectionOptions() { EncryptedFields = encryptedFieldsStr != null ? BsonDocument.Parse(encryptedFieldsStr) : null };
effectiveEncryptedFields = await subject.CreateEncryptedCollectionAsync(database, collectionName, createCollectionOptions, kmsProvider, dataKeyOptions);
Copy link
Contributor

Choose a reason for hiding this comment

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

createCollectionResult instead of effectiveEncryptedFields?

Copy link
Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor

@BorisDog BorisDog left a comment

Choose a reason for hiding this comment

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

minor comments

var exception = Record.Exception(() => subject.CreateEncryptedCollection(database, collectionName, createCollectionOptions, kmsProvider, dataKeyOptions));
AssertResults(exception, createCollectionOptions);

createCollectionOptions = new CreateCollectionOptions() { EncryptedFields = BsonDocument.Parse(encryptedFieldsStr) };
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to recreate createCollectionOptions.

Copy link
Author

Choose a reason for hiding this comment

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

missed, done


internal override CreateCollectionOptions Clone()
{
var clone = new CreateCollectionOptions<TDocument>();
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: you could use initialization syntax.
var = new CreateCollectionOptions() { x= y ... }

Copy link
Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor

@BorisDog BorisDog left a comment

Choose a reason for hiding this comment

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

LGTM.

@DmitryLukyanov DmitryLukyanov merged commit 0bb42fa into mongodb:master Jan 17, 2023
dnickless pushed a commit to dnickless/mongo-csharp-driver that referenced this pull request Aug 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants