Skip to content

Commit

Permalink
ClientEncryption: Adds dependency on the latest preview SDK version w…
Browse files Browse the repository at this point in the history
…ith Algorithm in EncryptionKeyWrapMetadata (#3066)

1) Make encryption package depend on latest SDK preview (3.26.0-preview) - Implement DeleteAllItemsByPartitionKeyStreamAsync as pass through since it doesn't require anything specific in relation to client encryption (partition keys may not be encrypted using client side encryption). Add validation on client encryption key create/rewrap APIs to only allow the RSA-OAEP algorithm for wrapping as that is the only wrap algorithm supported as of now.
2) Improve public documentation of client encryption.
3) Rename EncryptionAlgorithm to DataEncryptionAlgorithm (it was just changed from DataEncryptionKeyAlgorithm) to avoid conflicts with EncryptionAlgorithm in the Azure Key vault package (to make it easier for consumers rather than them needing to disambiguate by namespace).
4) Bump encryption package version to be able to release new package and update changelog.
  • Loading branch information
abhijitpai authored Mar 7, 2022
1 parent af9b009 commit 729e135
Show file tree
Hide file tree
Showing 16 changed files with 225 additions and 145 deletions.
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ClientPreviewVersion>3.26.0</ClientPreviewVersion>
<ClientPreviewSuffixVersion>preview</ClientPreviewSuffixVersion>
<DirectVersion>3.24.1</DirectVersion>
<EncryptionVersion>1.0.0-previewV19</EncryptionVersion>
<EncryptionVersion>1.0.0-previewV20</EncryptionVersion>
<CustomEncryptionVersion>1.0.0-preview02</CustomEncryptionVersion>
<HybridRowVersion>1.1.0-preview3</HybridRowVersion>
<LangVersion>9.0</LangVersion>
Expand Down
6 changes: 6 additions & 0 deletions Microsoft.Azure.Cosmos.Encryption/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ 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="1.0.0-previewV20"/> [1.0.0-previewV20](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/1.0.0-previewV20) - 2022-03-07

#### Added
- [#3066](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3066) Adds dependency on the latest preview SDK version with Algorithm in EncryptionKeyWrapMetadata.
- [#3050](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3050) Adds the use of Azure.Core interfaces in public surface.

### <a name="1.0.0-previewV19"/> [1.0.0-previewV19](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/1.0.0-previewV19) - 2022-01-13

#### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace Microsoft.Azure.Cosmos.Encryption
{
/// <summary>
/// Represents the encryption algorithms supported for data encryption.
/// Encryption algorithms supported for data encryption.
/// </summary>
public static class EncryptionAlgorithm
public static class DataEncryptionAlgorithm
{
/// <summary>
/// Represents the authenticated encryption algorithm with associated data as described in
Expand Down
21 changes: 11 additions & 10 deletions Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,17 @@ public override async Task<FeedResponse<T>> ReadManyItemsAsync<T>(
return this.ResponseFactory.CreateItemFeedResponse<T>(responseMessage);
}

public override Task<ResponseMessage> DeleteAllItemsByPartitionKeyStreamAsync(
Cosmos.PartitionKey partitionKey,
RequestOptions requestOptions = null,
CancellationToken cancellationToken = default)
{
return this.container.DeleteAllItemsByPartitionKeyStreamAsync(
partitionKey,
requestOptions,
cancellationToken);
}

public async Task<EncryptionSettings> GetOrUpdateEncryptionSettingsFromCacheAsync(
EncryptionSettings obsoleteEncryptionSettings,
CancellationToken cancellationToken)
Expand All @@ -730,16 +741,6 @@ public async Task<EncryptionSettings> GetOrUpdateEncryptionSettingsFromCacheAsyn
cancellationToken: cancellationToken);
}

#if SDKPROJECTREF
public override Task<ResponseMessage> DeleteAllItemsByPartitionKeyStreamAsync(
Cosmos.PartitionKey partitionKey,
RequestOptions requestOptions = null,
CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
#endif

/// <summary>
/// This function handles the scenario where a container is deleted(say from different Client) and recreated with same Id but with different client encryption policy.
/// The idea is to have the container Rid cached and sent out as part of RequestOptions with Container Rid set in "x-ms-cosmos-intended-collection-rid" header.
Expand Down
101 changes: 58 additions & 43 deletions Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,33 @@ namespace Microsoft.Azure.Cosmos.Encryption
using Microsoft.Azure.Cosmos.Linq;

/// <summary>
/// This class provides extension methods for <see cref="Container"/>.
/// Extension methods for <see cref="Container"/> to support client-side encryption.
/// </summary>
public static class EncryptionContainerExtensions
{
/// <summary>
/// Initializes and Caches the Client Encryption Policy and the corresponding keys configured for the container.
/// All the keys configured as per the Client Encryption Policy for the container must be created before its used in the policy.
/// Warms up the caches for the client encryption policy and the corresponding client encryption keys configured for the container.
/// This may be used to help improve latencies for the initial requests on the container from the client.
/// If this is not explicitly invoked, the caches are built when requests needing encryption/decryption are made.
/// </summary>
/// <param name="container">Encryption Container.</param>
/// <param name="cancellationToken"> cancellation token </param>
/// <returns>Container to perform operations supporting client-side encryption / decryption.</returns>
/// <param name="container">Container instance from client supporting encryption.</param>
/// <param name="cancellationToken">Token for request cancellation.</param>
/// <returns>Container with encryption-related caches warmed up.</returns>
/// <example>
/// This example shows how to get a Container with Encryption support and Initialize it with InitializeEncryptionAsync which allows for pre-fetching the
/// encryption policy and the encryption keys for caching.
/// This example shows how to get a container with encryption support and warm up the encryption-related caches.
///
/// <code language="c#">
/// <![CDATA[
/// CosmosClient cosmosClient = new CosmosClient();
/// cosmosClient.WithEncryption(azureKeyVaultKeyWrapProvider);
/// containerWithEncryption = await this.cosmosDatabase.GetContainer("id").InitializeEncryptionAsync();
/// Azure.Core.TokenCredential tokenCredential = new Azure.Identity.DefaultAzureCredential();
/// Azure.Core.Cryptography.IKeyEncryptionKeyResolver keyResolver = new Azure.Security.KeyVault.Keys.Cryptography.KeyResolver(tokenCredential);
/// CosmosClient client = (new CosmosClient(endpoint, authKey)).WithEncryption(keyResolver, KeyEncryptionKeyResolverName.AzureKeyVault);
/// Container container = await client.GetDatabase("databaseId").GetContainer("containerId").InitializeEncryptionAsync();
/// ]]>
/// </code>
/// </example>
/// <remarks>
/// See <see href="https://aka.ms/CosmosClientEncryption">client-side encryption documentation</see> for more details.
/// </remarks>
public static async Task<Container> InitializeEncryptionAsync(
this Container container,
CancellationToken cancellationToken = default)
Expand All @@ -42,7 +46,7 @@ public static async Task<Container> InitializeEncryptionAsync(

if (container is not EncryptionContainer encryptionContainer)
{
throw new ArgumentOutOfRangeException($"{nameof(InitializeEncryptionAsync)} requires the use of an encryption - enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details. ");
throw new ArgumentOutOfRangeException($"{nameof(InitializeEncryptionAsync)} requires the use of an encryption-enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details.");
}

await encryptionContainer.GetOrUpdateEncryptionSettingsFromCacheAsync(obsoleteEncryptionSettings: null, cancellationToken: cancellationToken);
Expand All @@ -51,30 +55,33 @@ public static async Task<Container> InitializeEncryptionAsync(
}

/// <summary>
/// This method gets the FeedIterator from LINQ IQueryable to execute query asynchronously.
/// This will create the fresh new FeedIterator when called which will support decryption.
/// Creates a FeedIterator from a LINQ IQueryable to be able to execute the query asynchronously.
/// This has support for decrypting results.
/// </summary>
/// <typeparam name="T">the type of object to query.</typeparam>
/// <param name="container">the encryption container.</param>
/// <param name="query">the IQueryable{T} to be converted.</param>
/// <returns>An iterator to go through the items.</returns>
/// <typeparam name="T">The type of object to query.</typeparam>
/// <param name="container">Container instance from client supporting encryption.</param>
/// <param name="query">The <see cref="IQueryable{T}" /> to be converted.</param>
/// <returns>An iterator to go through the results.</returns>
/// <example>
/// This example shows how to get FeedIterator from LINQ.
/// This example shows how to get a FeedIterator from an IQueryable with support to decrypt results.
///
/// <code language="c#">
/// <![CDATA[
/// IOrderedQueryable<ToDoActivity> linqQueryable = this.container.GetItemLinqQueryable<ToDoActivity>();
/// FeedIterator setIterator = this.container.ToEncryptionFeedIterator<ToDoActivity>(linqQueryable);
/// IOrderedQueryable<ToDoActivity> linqQueryable = container.GetItemLinqQueryable<ToDoActivity>();
/// FeedIterator<ToDoActivity> resultIterator = container.ToEncryptionFeedIterator<ToDoActivity>(linqQueryable);
/// ]]>
/// </code>
/// </example>
/// <remarks>
/// See <see href="https://aka.ms/CosmosClientEncryption">client-side encryption documentation</see> for more details.
/// </remarks>
public static FeedIterator<T> ToEncryptionFeedIterator<T>(
this Container container,
IQueryable<T> query)
{
if (container is not EncryptionContainer encryptionContainer)
{
throw new ArgumentOutOfRangeException(nameof(query), $"{nameof(ToEncryptionFeedIterator)} requires the use of an encryption - enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details. ");
throw new ArgumentOutOfRangeException(nameof(query), $"{nameof(ToEncryptionFeedIterator)} requires the use of an encryption-enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details.");
}

return new EncryptionFeedIterator<T>(
Expand All @@ -83,30 +90,33 @@ public static FeedIterator<T> ToEncryptionFeedIterator<T>(
}

/// <summary>
/// This method gets the FeedIterator from LINQ IQueryable to execute query asynchronously.
/// This will create the fresh new FeedIterator when called which will support decryption.
/// Creates a FeedIterator from a LINQ IQueryable to be able to execute the query asynchronously.
/// This has support for decrypting results.
/// </summary>
/// <typeparam name="T">the type of object to query.</typeparam>
/// <param name="container">the encryption container.</param>
/// <param name="query">the IQueryable{T} to be converted.</param>
/// <returns>An iterator to go through the items.</returns>
/// <typeparam name="T">The type of object to query.</typeparam>
/// <param name="container">Container instance from client supporting encryption.</param>
/// <param name="query">The <see cref="IQueryable{T}" /> to be converted.</param>
/// <returns>An iterator to go through the results.</returns>
/// <example>
/// This example shows how to get FeedIterator from LINQ.
///
/// <code language="c#">
/// <![CDATA[
/// IOrderedQueryable<ToDoActivity> linqQueryable = this.container.GetItemLinqQueryable<ToDoActivity>();
/// FeedIterator setIterator = this.container.ToEncryptionStreamIterator<ToDoActivity>(linqQueryable);
/// FeedIterator resultIterator = this.container.ToEncryptionStreamIterator<ToDoActivity>(linqQueryable);
/// ]]>
/// </code>
/// </example>
/// <remarks>
/// See <see href="https://aka.ms/CosmosClientEncryption">client-side encryption documentation</see> for more details.
/// </remarks>
public static FeedIterator ToEncryptionStreamIterator<T>(
this Container container,
IQueryable<T> query)
{
if (container is not EncryptionContainer encryptionContainer)
{
throw new ArgumentOutOfRangeException(nameof(query), $"{nameof(ToEncryptionStreamIterator)} requires the use of an encryption - enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details. ");
throw new ArgumentOutOfRangeException(nameof(query), $"{nameof(ToEncryptionStreamIterator)} requires the use of an encryption-enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details.");
}

return new EncryptionFeedIterator(
Expand All @@ -116,26 +126,31 @@ public static FeedIterator ToEncryptionStreamIterator<T>(
}

/// <summary>
/// Create a Microsoft.Azure.Cosmos.QueryDefinition with encryption support.
/// Creates an instance of <see cref="QueryDefinition" /> with support to add parameters
/// corresponding to encrypted properties.
/// </summary>
/// <param name="container"> The encryption container.</param>
/// <param name="queryText"> A valid Cosmos SQL query "Select * from test t" </param>
/// <returns> Microsoft.Azure.Cosmos.QueryDefinition </returns>
/// <param name="container">Container instance from client supporting encryption.</param>
/// <param name="queryText">A valid Cosmos SQL query.</param>
/// <returns>A new instance of <see cref="QueryDefinition" /> with support to add encrypted parameters.</returns>
/// <example>
/// This example shows how to get a QueryDefinition with Encryption Support.
/// This example shows how to create a QueryDefinition with support to add encrypted parameters.
///
/// <code language="c#">
/// <![CDATA[
/// containerWithEncryption = await this.cosmosDatabase.GetContainer("id").InitializeEncryptionAsync();
/// QueryDefinition withEncryptedParameter = containerWithEncryption.CreateQueryDefinition(
/// "SELECT * FROM c where c.PropertyName = @PropertyValue");
/// await withEncryptedParameter.AddParameterAsync(
/// "@PropertyName",
/// PropertyValue,
/// "/PropertyName");
/// QueryDefinition queryDefinitionWithEncryptedParameter = container.CreateQueryDefinition(
/// "SELECT * FROM c where c.SensitiveProperty = @FirstParameter");
/// await queryDefinitionWithEncryptedParameter.AddParameterAsync(
/// "@FirstParameter",
/// "sensitive value",
/// "/SensitiveProperty");
/// ]]>
/// </code>
/// </example>
/// <remarks>
/// Only equality comparisons are supported in the filter condition on encrypted properties.
/// These also require the property being filtered upon to be encrypted using <see cref="EncryptionType.Deterministic"/> encryption.
/// See <see href="https://aka.ms/CosmosClientEncryption">client-side encryption documentation</see> for more details.
/// </remarks>
public static QueryDefinition CreateQueryDefinition(this Container container, string queryText)
{
if (string.IsNullOrEmpty(queryText))
Expand All @@ -145,7 +160,7 @@ public static QueryDefinition CreateQueryDefinition(this Container container, st

if (container is not EncryptionContainer)
{
throw new ArgumentOutOfRangeException($"{nameof(CreateQueryDefinition)} requires the use of an encryption - enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details. ");
throw new ArgumentOutOfRangeException($"{nameof(CreateQueryDefinition)} requires the use of an encryption-enabled client. Please refer to https://aka.ms/CosmosClientEncryption for more details.");
}

return new EncryptionQueryDefinition(queryText, container);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ private async Task<ClientEncryptionKeyProperties> FetchClientEncryptionKeyProper
{
if (ex.StatusCode == HttpStatusCode.NotFound)
{
throw new InvalidOperationException($"Encryption Based Container without Client Encryption Keys. Please make sure you have created the Client Encryption Keys:{ex.Message}. Please refer to https://aka.ms/CosmosClientEncryption for more details. ");
throw new InvalidOperationException($"Encryption Based Container without Client Encryption Keys. Please make sure you have created the Client Encryption Keys:{ex.Message}. Please refer to https://aka.ms/CosmosClientEncryption for more details.");
}
else
{
Expand Down
Loading

0 comments on commit 729e135

Please sign in to comment.