-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Conversation
/// <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) |
There was a problem hiding this comment.
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
@@ -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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the collection name
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the collection name
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: sealed.
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blank line.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is nameof
applicable here?
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
src/MongoDB.Driver/Encryption/MongoEncryptionCreateCollectionException.cs
Show resolved
Hide resolved
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 }; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
createCollectionResult
instead of effectiveEncryptedFields
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this 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) }; |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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>(); |
There was a problem hiding this comment.
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 ... }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
No description provided.