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

ClientEncryption: Adds algorithm to EncryptionKeyWrapMetadata #3049

Merged
merged 4 commits into from
Feb 24, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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,
Expand Down Expand Up @@ -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
{
Expand All @@ -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);

}
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ namespace Microsoft.Azure.Cosmos
using Newtonsoft.Json.Linq;

/// <summary>
/// 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.
/// </summary>
#if PREVIEW
public
Expand All @@ -27,22 +28,24 @@ private EncryptionKeyWrapMetadata()
/// <summary>
/// Creates a new instance of key wrap metadata.
/// </summary>
/// <param name="type">ProviderName of KeyStoreProvider.</param>
/// <param name="name">Name of the metadata.</param>
/// <param name="value">Value of the metadata.</param>
public EncryptionKeyWrapMetadata(string type, string name, string value)
/// <param name="type">Identifier for the key resolver.</param>
/// <param name="name">Identifier for the customer managed key.</param>
/// <param name="value">Path to the customer managed key.</param>
/// <param name="algorithm">Algorithm used in wrapping and unwrapping of the data encryption key.</param>
public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm)
abhijitpai marked this conversation as resolved.
Show resolved Hide resolved
{
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));
abhijitpai marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
/// Creates a new instance of key wrap metadata based on an existing instance.
/// </summary>
/// <param name="source">Existing instance from which to initialize.</param>
public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source)
: this(source?.Type, source?.Name, source?.Value)
: this(source?.Type, source?.Name, source?.Value, source?.Algorithm)
{
}

Expand Down Expand Up @@ -70,6 +73,14 @@ public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source)
[JsonProperty(PropertyName = "value", NullValueHandling = NullValueHandling.Ignore)]
public string Value { get; private set; }

/// <summary>
/// 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.
/// </summary>
[JsonProperty(PropertyName = "algorithm", NullValueHandling = NullValueHandling.Ignore)]
public string Algorithm { get; private set; }

/// <summary>
/// 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.
Expand All @@ -91,6 +102,7 @@ public override int GetHashCode()
hashCode = (hashCode * -1521134295) + EqualityComparer<string>.Default.GetHashCode(this.Type);
hashCode = (hashCode * -1521134295) + EqualityComparer<string>.Default.GetHashCode(this.Name);
hashCode = (hashCode * -1521134295) + EqualityComparer<string>.Default.GetHashCode(this.Value);
hashCode = (hashCode * -1521134295) + EqualityComparer<string>.Default.GetHashCode(this.Algorithm);
return hashCode;
}

Expand All @@ -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);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -450,7 +450,7 @@ private static async Task<ClientEncryptionKeyProperties> 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);

Expand All @@ -474,7 +474,7 @@ private static async Task<ClientEncryptionKeyProperties> 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);
Expand All @@ -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);

Expand All @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down Expand Up @@ -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": {}
Expand Down