Skip to content

Commit

Permalink
Client Encryption: Adds validation code to check if the Key Vault URI…
Browse files Browse the repository at this point in the history
… provided in wrap metadata is a valid key identifier. (#3642)

* Check if the key vault uri provided is a valid Kid

* test fix.

* update changelog and build props

* Update Directory.Build.props

* Update Microsoft.Azure.Cosmos.Encryption.csproj

* Fixed preview version

* Refactor

* Update EncryptionDatabaseExtensions.cs
  • Loading branch information
kr-santosh committed Jan 19, 2023
1 parent 4b77519 commit 1710115
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 5 deletions.
5 changes: 2 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ClientOfficialVersion>3.31.2</ClientOfficialVersion>
<ClientPreviewVersion>3.31.2</ClientPreviewVersion>
<ClientPreviewSuffixVersion>preview</ClientPreviewSuffixVersion>
<DirectVersion>3.30.1</DirectVersion>
<EncryptionOfficialVersion>2.0.0</EncryptionOfficialVersion>
<EncryptionPreviewVersion>2.0.0</EncryptionPreviewVersion>
<EncryptionOfficialVersion>2.0.1</EncryptionOfficialVersion>
<EncryptionPreviewVersion>2.0.1</EncryptionPreviewVersion>
<EncryptionPreviewSuffixVersion>preview</EncryptionPreviewSuffixVersion>
<CustomEncryptionVersion>1.0.0-preview04</CustomEncryptionVersion>
<HybridRowVersion>1.1.0-preview3</HybridRowVersion>
Expand Down
10 changes: 10 additions & 0 deletions Microsoft.Azure.Cosmos.Encryption/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ Preview features are treated as a separate branch and will not be included in th
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### <a name="2.0.1"/> [2.0.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.1) - 2023-03-11

#### Added
- [#3642](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3642) Adds validation code to check if the Key Vault URI provided in wrap metadata is a valid key identifier.

### <a name="2.0.1-preview"/> [2.0.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.1-preview) - 2023-01-11

#### Added
- [#3642](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3642) Adds validation code to check if the Key Vault URI provided in wrap metadata is a valid key identifier.

### <a name="2.0.0"/> [2.0.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.0) - 2022-06-28

#### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ public static async Task<ClientEncryptionKeyResponse> CreateClientEncryptionKeyA
+ " Please refer to https://aka.ms/CosmosClientEncryption for more details.");
}

if (string.Equals(encryptionCosmosClient.KeyEncryptionKeyResolverName, KeyEncryptionKeyResolverName.AzureKeyVault))
{
// https://KEYVAULTNAME.vault.azure.net/keys/KEYNAME/KEYVERSION
string[] keyVaultUriSegments = new Uri(encryptionKeyWrapMetadata.Value).Segments;

if (keyVaultUriSegments.Length != 4 || !string.Equals(keyVaultUriSegments[1], "keys/", StringComparison.InvariantCultureIgnoreCase))
{
throw new ArgumentException($"Invalid Key Vault URI'{encryptionKeyWrapMetadata.Value}' passed. Pass the complete Azure keyvault key identifier. Please refer to https://aka.ms/CosmosClientEncryption for more details.");
}
}

KeyEncryptionKey keyEncryptionKey = KeyEncryptionKey.GetOrCreate(
encryptionKeyWrapMetadata.Name,
encryptionKeyWrapMetadata.Value,
Expand Down Expand Up @@ -192,6 +203,17 @@ public static async Task<ClientEncryptionKeyResponse> RewrapClientEncryptionKeyA
+ " Please refer to https://aka.ms/CosmosClientEncryption for more details.");
}

if (string.Equals(encryptionCosmosClient.KeyEncryptionKeyResolverName, KeyEncryptionKeyResolverName.AzureKeyVault))
{
// https://KEYVAULTNAME.vault.azure.net/keys/KEYNAME/KEYVERSION
string[] keyVaultUriSegments = new Uri(newEncryptionKeyWrapMetadata.Value).Segments;

if (keyVaultUriSegments.Length != 4 || !string.Equals(keyVaultUriSegments[1], "keys/", StringComparison.InvariantCultureIgnoreCase))
{
throw new ArgumentException($"Invalid Key Vault URI'{newEncryptionKeyWrapMetadata.Value}' passed. Pass the complete Azure keyvault key identifier. Please refer to https://aka.ms/CosmosClientEncryption for more details.");
}
}

ClientEncryptionKeyProperties clientEncryptionKeyProperties = await clientEncryptionKey.ReadAsync(cancellationToken: cancellationToken);

RequestOptions requestOptions = new RequestOptions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
</ItemGroup>

<ItemGroup Condition=" '$(SdkProjectRef)' != 'True' AND '$(IsPreview)' != 'True' ">
<PackageReference Include="Microsoft.Azure.Cosmos" Version="[3.28.0,3.29)" />
<PackageReference Include="Microsoft.Azure.Cosmos" Version="[3.31.0,3.32)" />
</ItemGroup>

<ItemGroup Condition=" '$(SdkProjectRef)' != 'True' AND '$(IsPreview)' == 'True' ">
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.28.0-preview" />
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.31.2-preview" />
</ItemGroup>

<ItemGroup Condition=" '$(SdkProjectRef)' == 'True' ">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,69 @@ await MdeEncryptionTests.CreateClientEncryptionKeyAsync(
if (ex is CosmosException cosmosException)
Assert.AreEqual(HttpStatusCode.Conflict, cosmosException.StatusCode);
}

cekId = "testAkvKid";
CosmosClient client = TestCommon.CreateCosmosClient();
TestKeyEncryptionKeyResolver testKeyEncryptionKeyResolver = new TestKeyEncryptionKeyResolver();

EncryptionKeyWrapMetadata metadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(KeyEncryptionKeyResolverName.AzureKeyVault, "key1", "https://testkeyvault.vault.azure.net/keys/testkey/12345678");

CosmosClient encryptionCosmosClient = client.WithEncryption(
testKeyEncryptionKeyResolver,
KeyEncryptionKeyResolverName.AzureKeyVault,
TimeSpan.Zero);

Database database = await encryptionCosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString());

ClientEncryptionKeyResponse clientEncrytionKeyResponse = await database.CreateClientEncryptionKeyAsync(
cekId,
DataEncryptionAlgorithm.AeadAes256CbcHmacSha256,
metadata);

Assert.AreEqual(HttpStatusCode.Created, clientEncrytionKeyResponse.StatusCode);

metadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(KeyEncryptionKeyResolverName.AzureKeyVault, "key1", "https://testkeyvault.vault.azure.net/keys/testkey/9101112");

clientEncrytionKeyResponse = await database.RewrapClientEncryptionKeyAsync(
cekId,
metadata);

Assert.AreEqual(HttpStatusCode.OK, clientEncrytionKeyResponse.StatusCode);

// complete key identifier not passed
metadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(KeyEncryptionKeyResolverName.AzureKeyVault, "key1", "https://testkeyvault.vault.azure.net/keys/testkey");

try
{
clientEncrytionKeyResponse = await database.CreateClientEncryptionKeyAsync(
cekId,
DataEncryptionAlgorithm.AeadAes256CbcHmacSha256,
metadata);

Assert.Fail("Key creation should have failed.");

}
catch(Exception ex)
{
Assert.AreEqual(true, ex.Message.Contains("Invalid Key Vault URI"));
}

// rewrap old key with new key vault uri without complete key identifier
try
{
clientEncrytionKeyResponse = await database.RewrapClientEncryptionKeyAsync(
cekId,
metadata);

Assert.Fail("Key rewrap should have failed.");

}
catch (Exception ex)
{
Assert.AreEqual(true, ex.Message.Contains("Invalid Key Vault URI"));
}

encryptionCosmosClient.Dispose();
}

[TestMethod]
Expand Down

0 comments on commit 1710115

Please sign in to comment.