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

Client Encryption: Adds code to support PartitionKey and Id encryption. #3241

Merged
merged 76 commits into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from 75 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
68f6266
support partition key and id encryption.
kr-santosh May 20, 2022
eec6f81
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh May 25, 2022
b47e86b
Update EncryptionContainer.cs
kr-santosh May 25, 2022
5e45c63
support hirarchical pk paths.
kr-santosh May 26, 2022
f661b87
pk none and null checks.
kr-santosh May 30, 2022
b609dce
Update MdeEncryptionTests.cs
kr-santosh May 30, 2022
1eb31dd
Update EncryptionContainer.cs
kr-santosh May 31, 2022
1cf7441
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh May 31, 2022
631375f
Update EncryptionContainer.cs
kr-santosh May 31, 2022
e9327db
updates
kr-santosh May 31, 2022
ad07dc0
fixes.
kr-santosh May 31, 2022
fc00a22
fixes to handle container delete scenarios for PK mismatch.
kr-santosh Jun 2, 2022
4573705
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jun 2, 2022
9acc868
Update MdeEncryptionTests.cs
kr-santosh Jun 2, 2022
0e7d795
Refactoring
kr-santosh Jun 2, 2022
db8370b
Updated tests.
kr-santosh Jun 3, 2022
80cf3ea
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jun 13, 2022
863e623
Update EncryptionProcessor.cs
kr-santosh Jun 13, 2022
0e03447
Merge branch 'users/sakulk/encPkgCepVer2' of https://github.com/Azure…
kr-santosh Jun 13, 2022
25d52a9
Update QueryDefinitionExtensions.cs
kr-santosh Jun 13, 2022
62d2b32
Update EncryptionProcessor.cs
kr-santosh Jun 13, 2022
0d277fb
Updated cosmos version
kr-santosh Jun 15, 2022
279ee4c
Update Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj
kr-santosh Jun 15, 2022
1c170d6
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jun 15, 2022
543768b
updated build prop and supported sdk version
kr-santosh Jun 16, 2022
4ac21e2
Update Microsoft.Azure.Cosmos.Encryption.csproj
kr-santosh Jun 16, 2022
4f01721
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jun 16, 2022
3cd9ac2
Update Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj
kr-santosh Jun 16, 2022
ee035d8
Merge branch 'users/sakulk/encPkgCepVer2' of https://github.com/Azure…
kr-santosh Jun 16, 2022
0992259
Update Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj
kr-santosh Jun 16, 2022
e90ab4e
Update Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj
kr-santosh Jun 16, 2022
86ea346
Fixes
kr-santosh Jun 16, 2022
efe33cc
Fixed preview tests.
kr-santosh Jun 17, 2022
2fa0eb7
Fixes as per review comments.
kr-santosh Jun 17, 2022
81d2734
Update EncryptionContainer.cs
kr-santosh Jun 17, 2022
b3cd23f
Update EncryptionContainer.cs
kr-santosh Jun 17, 2022
f27db84
Update EncryptionContainer.cs
kr-santosh Jun 17, 2022
c06c5b8
fixes issue with nested PK path encryption.
kr-santosh Jun 17, 2022
abbb406
Update changelog.md
kr-santosh Jun 17, 2022
4f77fac
Fixes.
kr-santosh Jun 20, 2022
e68ee0a
Update EncryptionProcessor.cs
kr-santosh Jun 20, 2022
ddbc70f
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jun 22, 2022
04791c9
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jun 27, 2022
8ee979d
Update EncryptionProcessor.cs
kr-santosh Jun 27, 2022
cde2916
Update MdeEncryptionTests.cs
kr-santosh Jun 28, 2022
62b5822
Add preview flag for Encryption Emulator tests.
kr-santosh Jun 28, 2022
ec64c05
Update build-preview.yml
kr-santosh Jun 28, 2022
81d06f8
Update MdeEncryptionTests.cs
kr-santosh Jun 28, 2022
a56820d
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jun 28, 2022
ad4d04d
Update build-preview.yml
kr-santosh Jun 28, 2022
daa2b4d
Update EncryptionProcessor.cs
kr-santosh Jun 28, 2022
4faf6d2
Fixes
kr-santosh Jun 28, 2022
20449a8
Update Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj
kr-santosh Jun 28, 2022
e1e89a2
Update Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj
kr-santosh Jun 28, 2022
17de3df
Update changelog.md
kr-santosh Jun 28, 2022
ba93847
Update EncryptionContainer.cs
kr-santosh Jun 28, 2022
6dd79a5
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jun 29, 2022
113eb81
Update EncryptionProcessor.cs
kr-santosh Jun 30, 2022
63f8ef9
fixes as per review comments. Fixed serializer used.
kr-santosh Jul 1, 2022
d775ef8
Update Microsoft.Azure.Cosmos.Encryption.csproj
kr-santosh Jul 1, 2022
2470c63
Update build-preview.yml
kr-santosh Jul 1, 2022
0ced97e
updated build flags and preview test.
kr-santosh Jul 1, 2022
c6e31fb
Fix test run check
kr-santosh Jul 1, 2022
6fe710d
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jul 1, 2022
835052d
Update Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj
kr-santosh Jul 1, 2022
39659d6
Merge branch 'users/sakulk/encPkgCepVer2' of https://github.com/Azure…
kr-santosh Jul 1, 2022
b5e7608
Fixed PK encryption in GetItemQueryStreamIterator feed range.
kr-santosh Jul 1, 2022
282c25a
dispose clients in tests.
kr-santosh Jul 1, 2022
35f7160
Update EncryptionProcessor.cs
kr-santosh Jul 1, 2022
00e88e1
move async calls from getqueryiterator to ReadNextAsync
kr-santosh Jul 1, 2022
9e9b10c
fixes in ENCRYPTIONPREVIEW flagged code
kr-santosh Jul 1, 2022
d1b3ef5
Update EncryptionFeedIterator.cs
kr-santosh Jul 2, 2022
b1bbb3e
Update EncryptionFeedIterator.cs
kr-santosh Jul 2, 2022
5bc2a7f
Merge branch 'master' into users/sakulk/encPkgCepVer2
kr-santosh Jul 25, 2022
fa8f35f
Update EncryptionFeedIterator.cs
kr-santosh Jul 25, 2022
1360980
Merge branch 'master' into users/sakulk/encPkgCepVer2
ealsur Jul 26, 2022
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
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<ClientPreviewVersion>3.29.0</ClientPreviewVersion>
<ClientPreviewSuffixVersion>preview</ClientPreviewSuffixVersion>
<DirectVersion>3.29.1</DirectVersion>
<EncryptionOfficialVersion>1.0.1</EncryptionOfficialVersion>
<EncryptionPreviewVersion>1.0.1</EncryptionPreviewVersion>
<EncryptionOfficialVersion>2.0.0</EncryptionOfficialVersion>
<EncryptionPreviewVersion>2.0.0</EncryptionPreviewVersion>
<EncryptionPreviewSuffixVersion>preview</EncryptionPreviewSuffixVersion>
<CustomEncryptionVersion>1.0.0-preview03</CustomEncryptionVersion>
<HybridRowVersion>1.1.0-preview3</HybridRowVersion>
Expand Down
9 changes: 9 additions & 0 deletions Microsoft.Azure.Cosmos.Encryption/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ 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.0"/> [2.0.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.0) - 2022-06-28

#### Added
- [#3241](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3241) Adds code to support PartitionKey and Id encryption.

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

#### Added
- [#3241](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3241) Adds code to support PartitionKey and Id encryption.

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

Expand Down
3 changes: 2 additions & 1 deletion Microsoft.Azure.Cosmos.Encryption/src/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ internal static class Constants
public const string DiagnosticsStartTime = "Start time";
public const string DocumentsResourcePropertyName = "Documents";
public const string IncorrectContainerRidSubStatus = "1024";
public const string PartitionKeyMismatch = "1001";

// TODO: Good to have constants available in the Cosmos SDK. Tracked via https://github.com/Azure/azure-cosmos-dotnet-v3/issues/2431
public const string IntendedCollectionHeader = "x-ms-cosmos-intended-collection-rid";
public const string IsClientEncryptedHeader = "x-ms-cosmos-is-client-encrypted";
public const string AllowCachedReadsHeader = "x-ms-cosmos-allow-cachedreads";
public const string DatabaseRidHeader = "x-ms-cosmos-database-rid";
public const string SubStatusHeader = "x-ms-substatus";
public const int SupportedClientEncryptionPolicyFormatVersion = 1;
public const int SupportedClientEncryptionPolicyFormatVersion = 2;
}
}
340 changes: 267 additions & 73 deletions Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs

Large diffs are not rendered by default.

170 changes: 163 additions & 7 deletions Microsoft.Azure.Cosmos.Encryption/src/EncryptionFeedIterator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,128 @@ namespace Microsoft.Azure.Cosmos.Encryption
{
using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

internal sealed class EncryptionFeedIterator : FeedIterator
{
private readonly FeedIterator feedIterator;
private readonly SemaphoreSlim singleIteratorInitSema = new SemaphoreSlim(1, 1);
private readonly EncryptionContainer encryptionContainer;
private readonly RequestOptions requestOptions;
private readonly QueryDefinition queryDefinition;
private readonly string queryText;
private readonly string continuationToken;
private readonly FeedRange feedRange;
private readonly QueryType queryType;

private bool isIteratorInitialized = false;

public EncryptionFeedIterator(
FeedIterator feedIterator,
EncryptionContainer encryptionContainer,
RequestOptions requestOptions)
{
this.feedIterator = feedIterator ?? throw new ArgumentNullException(nameof(feedIterator));
this.FeedIterator = feedIterator ?? throw new ArgumentNullException(nameof(feedIterator));
this.encryptionContainer = encryptionContainer ?? throw new ArgumentNullException(nameof(encryptionContainer));
this.requestOptions = requestOptions ?? throw new ArgumentNullException(nameof(requestOptions));
}

public override bool HasMoreResults => this.feedIterator.HasMoreResults;
public EncryptionFeedIterator(
EncryptionContainer encryptionContainer,
QueryDefinition queryDefinition,
string continuationToken = null,
QueryRequestOptions requestOptions = null)
{
this.encryptionContainer = encryptionContainer ?? throw new ArgumentNullException(nameof(encryptionContainer));
this.queryDefinition = queryDefinition;
this.continuationToken = continuationToken;
this.requestOptions = requestOptions;

this.FeedIterator = encryptionContainer.Container.GetItemQueryStreamIterator(
queryDefinition,
continuationToken,
requestOptions);

this.queryType = QueryType.QueryDefinitionType;
}

public EncryptionFeedIterator(
EncryptionContainer encryptionContainer,
string queryText = null,
string continuationToken = null,
QueryRequestOptions requestOptions = null)
{
this.encryptionContainer = encryptionContainer ?? throw new ArgumentNullException(nameof(encryptionContainer));
this.queryText = queryText;
this.continuationToken = continuationToken;
this.requestOptions = requestOptions;

this.FeedIterator = encryptionContainer.Container.GetItemQueryStreamIterator(
queryText,
continuationToken,
requestOptions);

this.queryType = QueryType.QueryTextType;
}

public EncryptionFeedIterator(
EncryptionContainer encryptionContainer,
ChangeFeedStartFrom changeFeedStartFrom,
ChangeFeedMode changeFeedMode,
ChangeFeedRequestOptions changeFeedRequestOptions = null)
{
this.encryptionContainer = encryptionContainer ?? throw new ArgumentNullException(nameof(encryptionContainer));
this.requestOptions = changeFeedRequestOptions;
this.FeedIterator = encryptionContainer.Container.GetChangeFeedStreamIterator(
changeFeedStartFrom,
changeFeedMode,
changeFeedRequestOptions);
}

public EncryptionFeedIterator(
EncryptionContainer encryptionContainer,
FeedRange feedRange,
QueryDefinition queryDefinition,
string continuationToken,
QueryRequestOptions requestOptions = null)
{
this.encryptionContainer = encryptionContainer ?? throw new ArgumentNullException(nameof(encryptionContainer));
this.feedRange = feedRange;
this.queryDefinition = queryDefinition;
this.continuationToken = continuationToken;
this.requestOptions = requestOptions;

this.FeedIterator = encryptionContainer.Container.GetItemQueryStreamIterator(
feedRange,
queryDefinition,
continuationToken,
requestOptions);

this.queryType = QueryType.QueryDefinitionWithFeedRangeType;
}

private enum QueryType
{
QueryWithoutEncryptedPk = 0,
QueryTextType = 1,
QueryDefinitionType = 2,
QueryDefinitionWithFeedRangeType = 3,
}

public override bool HasMoreResults => this.FeedIterator.HasMoreResults;

private FeedIterator FeedIterator { get; set; }

public override async Task<ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default)
{
EncryptionSettings encryptionSettings = await this.encryptionContainer.GetOrUpdateEncryptionSettingsFromCacheAsync(obsoleteEncryptionSettings: null, cancellationToken: cancellationToken);
encryptionSettings.SetRequestHeaders(this.requestOptions);
await this.GetIteratorWithEncryptionHeaderAndEncryptPartitionKeyIfRequiredAsync(encryptionSettings);

ResponseMessage responseMessage = await this.feedIterator.ReadNextAsync(cancellationToken);
ResponseMessage responseMessage = await this.FeedIterator.ReadNextAsync(cancellationToken);

EncryptionDiagnosticsContext encryptionDiagnosticsContext = new EncryptionDiagnosticsContext();

// check for Bad Request and Wrong RID intended and update the cached RID and Client Encryption Policy.
// check for Bad Request and Wrong intended RID and update the cached RID and Client Encryption Policy.
await this.encryptionContainer.ThrowIfRequestNeedsARetryPostPolicyRefreshAsync(responseMessage, encryptionSettings, encryptionDiagnosticsContext, cancellationToken);

if (responseMessage.IsSuccessStatusCode && responseMessage.Content != null)
Expand All @@ -55,5 +145,71 @@ public override async Task<ResponseMessage> ReadNextAsync(CancellationToken canc

return responseMessage;
}

private async Task GetIteratorWithEncryptionHeaderAndEncryptPartitionKeyIfRequiredAsync(EncryptionSettings encryptionSettings)
{
encryptionSettings.SetRequestHeaders(this.requestOptions);

// should be fine, flag is set at the end of init
if (this.isIteratorInitialized || this.queryType == QueryType.QueryWithoutEncryptedPk)
{
return;
}

if (await this.singleIteratorInitSema.WaitAsync(-1))
{
if (!this.isIteratorInitialized)
{
try
{
if (this.requestOptions is QueryRequestOptions queryRequestOptions)
{
if (queryRequestOptions != null && queryRequestOptions.PartitionKey.HasValue)
{
(queryRequestOptions.PartitionKey, bool isPkEncrypted) = await this.encryptionContainer.CheckIfPkIsEncryptedAndGetEncryptedPkAsync(
queryRequestOptions.PartitionKey.Value,
encryptionSettings,
cancellationToken: default);

if (!isPkEncrypted)
{
this.isIteratorInitialized = true;
return;
}
}

// we rebuild iterators which take in request options with partiton key and if partition key was encrypted.
this.FeedIterator = this.queryType switch
{
QueryType.QueryTextType => this.encryptionContainer.Container.GetItemQueryStreamIterator(
this.queryText,
this.continuationToken,
queryRequestOptions),
QueryType.QueryDefinitionType => this.encryptionContainer.Container.GetItemQueryStreamIterator(
this.queryDefinition,
this.continuationToken,
queryRequestOptions),
QueryType.QueryDefinitionWithFeedRangeType => this.encryptionContainer.Container.GetItemQueryStreamIterator(
this.feedRange,
this.queryDefinition,
this.continuationToken,
queryRequestOptions),
_ => this.FeedIterator,
};
}

this.isIteratorInitialized = true;
}
finally
{
this.singleIteratorInitSema.Release(1);
}
}
else
{
this.singleIteratorInitSema.Release(1);
}
}
}
}
}
Loading