From a9a7100c8d00b6025a8af939949b9618a2effaf4 Mon Sep 17 00:00:00 2001 From: Santosh Kulkarni <66682828+kr-santosh@users.noreply.github.com> Date: Wed, 24 Mar 2021 00:34:57 +0530 Subject: [PATCH] Client Encryption : Adds support to expose Type in EncryptionKeyWrapMetadata constructor. (#2283) * Exposes Type in EncryptionKeyWrapMetadata. * Update ContainerSettingsTests.cs * Update EncryptionKeyWrapMetadata.cs * Removed algorithm from metadata * Removed private set. * Update DotNetPreviewSDKAPI.json * Make Type Public. Revert public set. * Updated Comment description Co-authored-by: j82w --- .../EncryptionKeyWrapMetadata.cs | 31 ++++++++----------- .../Settings/ClientEncryptionPolicy.cs | 5 +-- .../CosmosDatabaseTests.cs | 13 ++++---- .../Fluent/ContainerSettingsTests.cs | 2 +- .../Contracts/DotNetPreviewSDKAPI.json | 18 +++++++++-- 5 files changed, 40 insertions(+), 29 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/EncryptionKeyWrapMetadata.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/EncryptionKeyWrapMetadata.cs index 85ab7ffe93..e30babd71d 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/EncryptionKeyWrapMetadata.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/EncryptionKeyWrapMetadata.cs @@ -25,12 +25,15 @@ private EncryptionKeyWrapMetadata() /// /// Creates a new instance of key wrap metadata. - /// + /// + /// ProviderName of KeyStoreProvider. /// Name of the metadata. /// Value of the metadata. - public EncryptionKeyWrapMetadata(string name, string value) - : this(type: "custom", name: name, value: value) + public EncryptionKeyWrapMetadata(string type, string name, string value) { + this.Type = type ?? throw new ArgumentNullException(nameof(type)); + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + this.Value = value ?? throw new ArgumentNullException(nameof(value)); } /// @@ -38,23 +41,17 @@ public EncryptionKeyWrapMetadata(string name, string value) /// /// Existing instance from which to initialize. public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source) - : this(source?.Type, source?.Name, source?.Value, source?.Algorithm) + : this(source?.Type, source?.Name, source?.Value) { } - internal EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm = null) - { - this.Type = type ?? throw new ArgumentNullException(nameof(type)); - this.Name = name ?? throw new ArgumentNullException(nameof(name)); - this.Value = value ?? throw new ArgumentNullException(nameof(value)); - this.Algorithm = algorithm; - } - + /// + /// Serialized form of metadata. + /// Note: This value is saved in the Cosmos DB service. + /// Implementors of derived implementations should ensure that this does not have (private) key material or credential information. + /// [JsonProperty(PropertyName = "type", NullValueHandling = NullValueHandling.Ignore)] - internal string Type { get; private set; } - - [JsonProperty(PropertyName = "algorithm", NullValueHandling = NullValueHandling.Ignore)] - internal string Algorithm { get; private set; } + public string Type { get; private set; } /// /// Serialized form of metadata. @@ -84,7 +81,6 @@ public override int GetHashCode() { int hashCode = 1265339359; hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.Type); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.Algorithm); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.Name); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.Value); return hashCode; @@ -101,7 +97,6 @@ public bool Equals(EncryptionKeyWrapMetadata other) { return other != null && this.Type == other.Type && - this.Algorithm == other.Algorithm && this.Name == other.Name && this.Value == other.Value; } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/ClientEncryptionPolicy.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/ClientEncryptionPolicy.cs index 388ccb5372..4708acc410 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/ClientEncryptionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/ClientEncryptionPolicy.cs @@ -86,9 +86,10 @@ private void ValidateClientEncryptionIncludedPath(ClientEncryptionIncludedPath c } if (!string.Equals(clientEncryptionIncludedPath.EncryptionType, "Deterministic") && - !string.Equals(clientEncryptionIncludedPath.EncryptionType, "Randomized")) + !string.Equals(clientEncryptionIncludedPath.EncryptionType, "Randomized") && + !string.Equals(clientEncryptionIncludedPath.EncryptionType, "Plaintext")) { - throw new ArgumentException("EncryptionType should be either 'Deterministic' or 'Randomized'.", nameof(clientEncryptionIncludedPath)); + throw new ArgumentException("EncryptionType should be either 'Deterministic' or 'Randomized' or 'Plaintext'.", nameof(clientEncryptionIncludedPath)); } if (string.IsNullOrWhiteSpace(clientEncryptionIncludedPath.EncryptionAlgorithm)) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosDatabaseTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosDatabaseTests.cs index ca73645a5b..a769de0d83 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosDatabaseTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosDatabaseTests.cs @@ -416,7 +416,7 @@ public async Task EncryptionCreateReplaceCek() Assert.IsNotNull(cekProperties.ResourceId); Assert.AreEqual( - new EncryptionKeyWrapMetadata("metadataName", "metadataValue"), + new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue"), cekProperties.EncryptionKeyWrapMetadata); // Use a different client instance to avoid (unintentional) cache impact @@ -433,7 +433,7 @@ public async Task EncryptionCreateReplaceCek() Assert.IsNotNull(cekProperties.ResourceId); Assert.AreEqual( - new EncryptionKeyWrapMetadata("metadataName", "updatedMetadataValue"), + new EncryptionKeyWrapMetadata("custom", "metadataName", "updatedMetadataValue"), cekProperties.EncryptionKeyWrapMetadata); // Use a different client instance to avoid (unintentional) cache impact @@ -454,7 +454,7 @@ private static async Task CreateCekAsync(Database rngCsp.GetBytes(rawCek); } - ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek, new EncryptionKeyWrapMetadata("metadataName", "metadataValue")); + ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek, new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue")); ClientEncryptionKeyResponse cekResponse = await databaseCore.CreateClientEncryptionKeyAsync(cekProperties); @@ -482,7 +482,7 @@ private static async Task ReplaceCekAsync(Databas rngCsp.GetBytes(rawCek); } - ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek, new EncryptionKeyWrapMetadata("metadataName", "updatedMetadataValue")); + ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek, new EncryptionKeyWrapMetadata("custom", "metadataName", "updatedMetadataValue")); ClientEncryptionKeyResponse cekResponse = await cek.ReplaceAsync(cekProperties); Assert.AreEqual(HttpStatusCode.OK, cekResponse.StatusCode); @@ -513,7 +513,7 @@ public async Task VerifyCekFeedIterator() rngCsp.GetBytes(rawCek1); } - ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek1, new EncryptionKeyWrapMetadata("metadataName", "metadataValue")); + ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek1, new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue")); ClientEncryptionKeyResponse cekResponse = await databaseCore.CreateClientEncryptionKeyAsync(cekProperties); @@ -528,7 +528,7 @@ public async Task VerifyCekFeedIterator() rngCsp.GetBytes(rawCek2); } - cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek2, new EncryptionKeyWrapMetadata("metadataName", "metadataValue")); + cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek2, new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue")); cekResponse = await databaseCore.CreateClientEncryptionKeyAsync(cekProperties); @@ -552,6 +552,7 @@ public async Task VerifyCekFeedIterator() { readDekIds.Add(clientEncryptionKeyProperties.Id); Assert.AreEqual("AEAD_AES_256_CBC_HMAC_SHA256", clientEncryptionKeyProperties.EncryptionAlgorithm); + Assert.AreEqual(cekProperties.EncryptionKeyWrapMetadata.Type, clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Type); Assert.AreEqual(cekProperties.EncryptionKeyWrapMetadata.Name, clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Name); Assert.AreEqual(cekProperties.EncryptionKeyWrapMetadata.Value, clientEncryptionKeyProperties.EncryptionKeyWrapMetadata.Value); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs index bfb95b1de7..7a6cdee948 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs @@ -677,7 +677,7 @@ public async Task WithClientEncryptionPolicyFailureTest() } catch (ArgumentException ex) { - Assert.IsTrue(ex.Message.Contains("EncryptionType should be either 'Deterministic' or 'Randomized'.")); + Assert.IsTrue(ex.Message.Contains("EncryptionType should be either 'Deterministic' or 'Randomized' or 'Plaintext'.")); } path1.EncryptionType = "Deterministic"; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index ee98d70409..ea690552dc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -801,6 +801,13 @@ ], "MethodInfo": "System.String get_Name();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.String get_Type()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_Type();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.String get_Value()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -815,6 +822,13 @@ ], "MethodInfo": "System.String Name;CanRead:True;CanWrite:True;System.String get_Name();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.String Type[Newtonsoft.Json.JsonPropertyAttribute(NullValueHandling = 1, PropertyName = \"type\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String Type;CanRead:True;CanWrite:True;System.String get_Type();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.String Value[Newtonsoft.Json.JsonPropertyAttribute(NullValueHandling = 1, PropertyName = \"value\")]": { "Type": "Property", "Attributes": [ @@ -827,10 +841,10 @@ "Attributes": [], "MethodInfo": "[Void .ctor(Microsoft.Azure.Cosmos.EncryptionKeyWrapMetadata), Void .ctor(Microsoft.Azure.Cosmos.EncryptionKeyWrapMetadata)]" }, - "Void .ctor(System.String, System.String)": { + "Void .ctor(System.String, System.String, System.String)": { "Type": "Constructor", "Attributes": [], - "MethodInfo": "[Void .ctor(System.String, System.String), Void .ctor(System.String, System.String)]" + "MethodInfo": "[Void .ctor(System.String, System.String, System.String), Void .ctor(System.String, System.String, System.String)]" } }, "NestedTypes": {}