diff --git a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs
index 5eccc58c7a..071f704bc2 100644
--- a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs
+++ b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs
@@ -45,8 +45,8 @@ public static async Task ClassInitialize(TestContext context)
DataEncryptionKeyCacheTimeToLive = null
};
- metadata1 = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "key1", "tempmetadata1");
- metadata2 = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "key2", "tempmetadata2");
+ metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "key1", "tempmetadata1");
+ metadata2 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "key2", "tempmetadata2");
MdeEncryptionTests.encryptionCosmosClient = MdeEncryptionTests.client.WithEncryption(testEncryptionKeyWrapProvider);
MdeEncryptionTests.database = await MdeEncryptionTests.encryptionCosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString());
@@ -60,7 +60,7 @@ await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
metadata2);
- EncryptionKeyWrapMetadata revokedKekmetadata = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "revokedKek", "revokedKek-metadata");
+ EncryptionKeyWrapMetadata revokedKekmetadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "revokedKek", "revokedKek-metadata");
await database.CreateClientEncryptionKeyAsync(
"keywithRevokedKek",
DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256,
@@ -257,18 +257,18 @@ public async Task EncryptionCreateClientEncryptionKey()
{
string cekId = "anotherCek";
- EncryptionKeyWrapMetadata metadata1 = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1");
+ EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1");
ClientEncryptionKeyProperties clientEncryptionKeyProperties = await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
cekId,
metadata1);
Assert.AreEqual(
- new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, name: cekId, value: metadata1.Value),
+ MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, name: cekId, value: metadata1.Value),
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata);
// creating another key with same id should fail
- metadata1 = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata2");
+ metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata2");
try
{
@@ -289,22 +289,22 @@ await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
public async Task EncryptionRewrapClientEncryptionKey()
{
string cekId = "rewrapkeytest";
- EncryptionKeyWrapMetadata metadata1 = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1");
+ EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1");
ClientEncryptionKeyProperties clientEncryptionKeyProperties = await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
cekId,
metadata1);
Assert.AreEqual(
- new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, name: cekId, value: metadata1.Value),
+ MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, name: cekId, value: metadata1.Value),
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata);
- EncryptionKeyWrapMetadata updatedMetaData = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, metadata1 + "updatedmetadata");
+ EncryptionKeyWrapMetadata updatedMetaData = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, metadata1 + "updatedmetadata");
clientEncryptionKeyProperties = await MdeEncryptionTests.RewarpClientEncryptionKeyAsync(
cekId,
updatedMetaData);
Assert.AreEqual(
- new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, name: cekId, value: updatedMetaData.Value),
+ MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, name: cekId, value: updatedMetaData.Value),
clientEncryptionKeyProperties.EncryptionKeyWrapMetadata);
}
@@ -435,7 +435,7 @@ public async Task EncryptionResourceTokenAuthRestricted()
try
{
string cekId = "testingcekID";
- EncryptionKeyWrapMetadata metadata1 = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1");
+ EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1");
ClientEncryptionKeyResponse clientEncrytionKeyResponse = await databaseForRestrictedUser.CreateClientEncryptionKeyAsync(
cekId,
@@ -450,7 +450,7 @@ public async Task EncryptionResourceTokenAuthRestricted()
try
{
string cekId = "testingcekID";
- EncryptionKeyWrapMetadata metadata1 = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1" + "updated");
+ EncryptionKeyWrapMetadata metadata1 = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, cekId, "testmetadata1" + "updated");
ClientEncryptionKeyResponse clientEncrytionKeyResponse = await databaseForRestrictedUser.RewrapClientEncryptionKeyAsync(
cekId,
@@ -1549,7 +1549,7 @@ public async Task EncryptionValidatePolicyRefreshPostDatabaseDelete()
DataEncryptionKeyCacheTimeToLive = TimeSpan.FromMinutes(30),
};
- EncryptionKeyWrapMetadata keyWrapMetadata = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "myCek", "mymetadata1");
+ EncryptionKeyWrapMetadata keyWrapMetadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider.ProviderName, "myCek", "mymetadata1");
CosmosClient encryptionCosmosClient = mainClient.WithEncryption(testEncryptionKeyWrapProvider);
Database mainDatabase = await encryptionCosmosClient.CreateDatabaseAsync("databaseToBeDeleted");
@@ -1615,7 +1615,7 @@ public async Task EncryptionValidatePolicyRefreshPostDatabaseDelete()
mainDatabase = await encryptionCosmosClient.CreateDatabaseAsync("databaseToBeDeleted");
- keyWrapMetadata = new EncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider2.ProviderName, "myCek", "mymetadata2");
+ keyWrapMetadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(testEncryptionKeyWrapProvider2.ProviderName, "myCek", "mymetadata2");
clientEncrytionKeyResponse = await mainDatabase.CreateClientEncryptionKeyAsync(
keyWrapMetadata.Name,
DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256,
@@ -2983,6 +2983,15 @@ private static void VerifyDiagnostics(
}
}
+ private static EncryptionKeyWrapMetadata CreateEncryptionKeyWrapMetadata(string type, string name, string value)
+ {
+#if SDKPROJECTREF
+ return new EncryptionKeyWrapMetadata(type, name, value, "algo");
+#else
+ return new EncryptionKeyWrapMetadata(type, name, value);
+#endif
+ }
+
public class TestDoc
{
diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/EncryptionKeyWrapMetadata.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/EncryptionKeyWrapMetadata.cs
index a5bc5e26aa..8047558303 100644
--- a/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/EncryptionKeyWrapMetadata.cs
+++ b/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/EncryptionKeyWrapMetadata.cs
@@ -10,7 +10,8 @@ namespace Microsoft.Azure.Cosmos
using Newtonsoft.Json.Linq;
///
- /// Metadata that a key wrapping provider can use to wrap/unwrap data encryption keys.
+ /// Metadata that can be used to wrap/unwrap a Data Encryption Key using a Customer Managed Key.
+ /// See https://aka.ms/CosmosClientEncryption for more information on client-side encryption support in Azure Cosmos DB.
///
#if PREVIEW
public
@@ -27,14 +28,16 @@ private EncryptionKeyWrapMetadata()
///
/// Creates a new instance of key wrap metadata.
///
- /// ProviderName of KeyStoreProvider.
- /// Name of the metadata.
- /// Value of the metadata.
- public EncryptionKeyWrapMetadata(string type, string name, string value)
+ /// Identifier for the key resolver.
+ /// Identifier for the customer managed key.
+ /// Path to the customer managed key.
+ /// Algorithm used in wrapping and unwrapping of the data encryption key.
+ public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm)
{
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 ?? throw new ArgumentNullException(nameof(algorithm));
}
///
@@ -42,7 +45,7 @@ public EncryptionKeyWrapMetadata(string type, string name, string value)
///
/// Existing instance from which to initialize.
public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source)
- : this(source?.Type, source?.Name, source?.Value)
+ : this(source?.Type, source?.Name, source?.Value, source?.Algorithm)
{
}
@@ -70,6 +73,14 @@ public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source)
[JsonProperty(PropertyName = "value", NullValueHandling = NullValueHandling.Ignore)]
public string Value { get; private set; }
+ ///
+ /// 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 = "algorithm", NullValueHandling = NullValueHandling.Ignore)]
+ public string Algorithm { get; private set; }
+
///
/// This contains additional values for scenarios where the SDK is not aware of new fields.
/// This ensures that if resource is read and updated none of the fields will be lost in the process.
@@ -91,6 +102,7 @@ public override int GetHashCode()
hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.Type);
hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.Name);
hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.Value);
+ hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.Algorithm);
return hashCode;
}
@@ -107,6 +119,7 @@ public bool Equals(EncryptionKeyWrapMetadata other)
this.Type == other.Type &&
this.Name == other.Name &&
this.Value == other.Value &&
+ this.Algorithm == other.Algorithm &&
this.AdditionalProperties.EqualsTo(other.AdditionalProperties);
}
}
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 b61b94757b..9370345d81 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("custom", "metadataName", "metadataValue"),
+ new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue", "algo"),
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("custom", "metadataName", "updatedMetadataValue"),
+ new EncryptionKeyWrapMetadata("custom", "metadataName", "updatedMetadataValue", "algo"),
cekProperties.EncryptionKeyWrapMetadata);
// Use a different client instance to avoid (unintentional) cache impact
@@ -450,7 +450,7 @@ private static async Task CreateCekAsync(Database
// Generate random bytes cryptographically.
byte[] rawCek = RandomNumberGenerator.GetBytes(32);
- ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek, new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue"));
+ ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek, new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue", "algo"));
ClientEncryptionKeyResponse cekResponse = await databaseCore.CreateClientEncryptionKeyAsync(cekProperties);
@@ -474,7 +474,7 @@ private static async Task ReplaceCekAsync(Databas
// Generate random bytes cryptographically.
byte[] rawCek = RandomNumberGenerator.GetBytes(32);
- ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek, new EncryptionKeyWrapMetadata("custom", "metadataName", "updatedMetadataValue"));
+ ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek, new EncryptionKeyWrapMetadata("custom", "metadataName", "updatedMetadataValue", "algo"));
ClientEncryptionKeyResponse cekResponse = await cek.ReplaceAsync(cekProperties);
Assert.AreEqual(HttpStatusCode.OK, cekResponse.StatusCode);
@@ -501,7 +501,7 @@ public async Task VerifyCekFeedIterator()
// Generate random bytes cryptographically.
byte[] rawCek1 = RandomNumberGenerator.GetBytes(32);
- ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek1, new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue"));
+ ClientEncryptionKeyProperties cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek1, new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue", "algo"));
ClientEncryptionKeyResponse cekResponse = await databaseCore.CreateClientEncryptionKeyAsync(cekProperties);
@@ -512,7 +512,7 @@ public async Task VerifyCekFeedIterator()
// Generate random bytes cryptographically.
byte[] rawCek2 = RandomNumberGenerator.GetBytes(32);
- cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek2, new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue"));
+ cekProperties = new ClientEncryptionKeyProperties(cekId, "AEAD_AES_256_CBC_HMAC_SHA256", rawCek2, new EncryptionKeyWrapMetadata("custom", "metadataName", "metadataValue", "algo"));
cekResponse = await databaseCore.CreateClientEncryptionKeyAsync(cekProperties);
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs
index 342422ac0e..97a5771620 100644
--- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs
+++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs
@@ -369,7 +369,7 @@ internal static async Task CreateClientEncryptionKey(
string dekId,
DatabaseInlineCore databaseInlineCore)
{
- EncryptionKeyWrapMetadata metadata = new EncryptionKeyWrapMetadata("custom", dekId, "tempMetadata");
+ EncryptionKeyWrapMetadata metadata = new EncryptionKeyWrapMetadata("custom", dekId, "tempMetadata", "algo");
// Generate random bytes cryptographically.
byte[] wrappedDataEncryptionKey = RandomNumberGenerator.GetBytes(32);
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 ad7e48bafb..1d51c448db 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
@@ -649,6 +649,20 @@
"Attributes": [],
"MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
},
+ "System.String Algorithm[Newtonsoft.Json.JsonPropertyAttribute(NullValueHandling = 1, PropertyName = \"algorithm\")]": {
+ "Type": "Property",
+ "Attributes": [
+ "JsonPropertyAttribute"
+ ],
+ "MethodInfo": "System.String Algorithm;CanRead:True;CanWrite:True;System.String get_Algorithm();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
+ },
+ "System.String get_Algorithm()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
+ "Type": "Method",
+ "Attributes": [
+ "CompilerGeneratedAttribute"
+ ],
+ "MethodInfo": "System.String get_Algorithm();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
+ },
"System.String get_Name()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
"Attributes": [
@@ -696,10 +710,10 @@
"Attributes": [],
"MethodInfo": "[Void .ctor(Microsoft.Azure.Cosmos.EncryptionKeyWrapMetadata), Void .ctor(Microsoft.Azure.Cosmos.EncryptionKeyWrapMetadata)]"
},
- "Void .ctor(System.String, System.String, System.String)": {
+ "Void .ctor(System.String, System.String, System.String, System.String)": {
"Type": "Constructor",
"Attributes": [],
- "MethodInfo": "[Void .ctor(System.String, System.String, System.String), Void .ctor(System.String, System.String, System.String)]"
+ "MethodInfo": "[Void .ctor(System.String, System.String, System.String, System.String), Void .ctor(System.String, System.String, System.String, System.String)]"
}
},
"NestedTypes": {}