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

[CosmosDB] Adds support to allow partition key and id paths to be part of client encryption policy. #18633

Merged
merged 24 commits into from
Jun 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
02b5575
Support client encryption policy during container creation
kr-santosh Apr 21, 2022
1dac6c0
Merge branch 'Azure:main' into users/sakulk/psCepSupport
kr-santosh Apr 21, 2022
27c5327
Update SqlOperationsTests.ps1
kr-santosh Apr 26, 2022
e2f7ab6
Update New-AzCosmosDBSqlContainer.md
kr-santosh Apr 26, 2022
6cd0df8
Update PSClientEncryptionPolicy.cs
kr-santosh May 5, 2022
5bfcd30
Update NewAzCosmosDBSqlContainer.cs
kr-santosh May 5, 2022
8f53054
Update ChangeLog.md
kr-santosh May 5, 2022
758a3ec
Updated package.
kr-santosh May 12, 2022
ff1cf28
Update CosmosDB.Test.csproj
kr-santosh May 12, 2022
5f01909
Merge branch 'main' into users/sakulk/psCepSupport
kr-santosh May 12, 2022
82bfd1d
Updated example, session records.
kr-santosh May 12, 2022
b2b444a
updated session records.
kr-santosh May 12, 2022
e0d6b72
Merge branch 'Azure:main' into users/sakulk/psCepSupport
kr-santosh May 13, 2022
b302997
Fixes update container command on containers with client encryption p…
kr-santosh Jun 13, 2022
a6efb1b
Merge branch 'main' into users/sakulk/psCepSupport
kr-santosh Jun 13, 2022
5253252
Update ChangeLog.md
kr-santosh Jun 13, 2022
b04c5b7
Update ChangeLog.md
kr-santosh Jun 13, 2022
a0e19e2
Support partition key and id paths to be part of client encryption po…
kr-santosh Jun 20, 2022
3edc9ef
Merge branch 'main' into users/sakulk/psCepSupport
kr-santosh Jun 20, 2022
be4c25f
Update ChangeLog.md
kr-santosh Jun 20, 2022
08c7bdc
Update New-AzCosmosDBSqlContainer.md
kr-santosh Jun 20, 2022
fd7a1b1
Update PSClientEncryptionPolicy.cs
kr-santosh Jun 21, 2022
6efbf8b
Update src/CosmosDB/CosmosDB/ChangeLog.md
kr-santosh Jun 21, 2022
5e6c819
Merge branch 'main' into users/sakulk/psCepSupport
VeryEarly Jun 23, 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
1 change: 1 addition & 0 deletions src/CosmosDB/CosmosDB/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
-->

## Upcoming Release
* Added support for partition key and id paths to be part of client encryption policy.
* Fixed bug related to Update-AzCosmosDBSqlContainer command on containers with Client Encryption Policy.

## Version 1.9.0
Expand Down
59 changes: 46 additions & 13 deletions src/CosmosDB/CosmosDB/Models/PSClientEncryptionPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public PSClientEncryptionPolicy(ClientEncryptionPolicy clientEncryptionPolicy)

if (ModelHelper.IsNotNullOrEmpty(clientEncryptionPolicy.IncludedPaths))
{
PSClientEncryptionPolicy.ValidateIncludedPaths(clientEncryptionPolicy.IncludedPaths);
PSClientEncryptionPolicy.ValidateIncludedPaths(clientEncryptionPolicy.IncludedPaths, (int)clientEncryptionPolicy.PolicyFormatVersion);

IncludedPaths = new List<PSClientEncryptionIncludedPath>();
foreach (ClientEncryptionIncludedPath key in clientEncryptionPolicy.IncludedPaths)
Expand Down Expand Up @@ -87,9 +87,12 @@ public static ClientEncryptionPolicy ToSDKModel(PSClientEncryptionPolicy pSClien
}
}

PSClientEncryptionPolicy.ValidatePartitionKeyPathsAreNotEncrypted(clientEncryptionPolicy.IncludedPaths, partitionKeyPathTokens);
PSClientEncryptionPolicy.ValidatePartitionKeyPathsAreNotEncrypted(
clientEncryptionPolicy.IncludedPaths,
partitionKeyPathTokens,
pSClientEncryptionPolicy.PolicyFormatVersion);

if(clientEncryptionPolicy.PolicyFormatVersion != 1)
if(clientEncryptionPolicy.PolicyFormatVersion < 1 || clientEncryptionPolicy.PolicyFormatVersion > 2)
{
throw new InvalidOperationException($"Invalid PolicyFormatVersion:{clientEncryptionPolicy.PolicyFormatVersion} used in Client Encryption Policy. ");
}
Expand All @@ -102,26 +105,44 @@ public static ClientEncryptionPolicy ToSDKModel(PSClientEncryptionPolicy pSClien
/// </summary>
/// <param name="clientEncryptionIncludedPath">Included paths of the client encryption policy.</param>
/// <param name="partitionKeyPathTokens">Tokens corresponding to validated partition key.</param>
private static void ValidatePartitionKeyPathsAreNotEncrypted(IEnumerable<ClientEncryptionIncludedPath> clientEncryptionIncludedPath, List<string> partitionKeyPathTokens)
/// <param name="policyFormatVersion">Client encryption policy format version.</param>
private static void ValidatePartitionKeyPathsAreNotEncrypted(
IEnumerable<ClientEncryptionIncludedPath> clientEncryptionIncludedPath,
List<string> partitionKeyPathTokens,
int policyFormatVersion)
{
Debug.Assert(partitionKeyPathTokens != null);
IEnumerable<string> propertiesToEncrypt = clientEncryptionIncludedPath.Select(p => p.Path.Substring(1));

foreach (string tokenInPath in partitionKeyPathTokens)
{
Debug.Assert(String.IsNullOrEmpty(tokenInPath));
if (propertiesToEncrypt.Contains(tokenInPath.Substring(1)))
Debug.Assert(String.IsNullOrEmpty(tokenInPath));

string topLevelPath = tokenInPath.Split('/')[1];
// paths in included paths start with "/". Get the ClientEncryptionIncludedPath and validate.
IEnumerable<ClientEncryptionIncludedPath> encryptedPartitionKeyPath = clientEncryptionIncludedPath.Where(p => p.Path.Substring(1).Equals(topLevelPath));

if (encryptedPartitionKeyPath.Any())
{
throw new ArgumentException($"Paths which are part of the partition key({tokenInPath}) may not be included in the Client Encryption Policy. ");
if (policyFormatVersion < 2)
{
throw new ArgumentException($"Path: {encryptedPartitionKeyPath.Select(et => et.Path).FirstOrDefault()} which is part of the partition key cannot be encrypted with PolicyFormatVersion: {policyFormatVersion}. Please use PolicyFormatVersion: 2. ");
}

// for the ClientEncryptionIncludedPath found check the encryption type.
if (encryptedPartitionKeyPath.Select(et => et.EncryptionType).FirstOrDefault() != "Deterministic")
{
throw new ArgumentException($"Path: {encryptedPartitionKeyPath.Select(et => et.Path).FirstOrDefault()} which is part of the partition key has to be encrypted with Deterministic type Encryption.");
}
}
}
}

private static void ValidateIncludedPaths(IEnumerable<ClientEncryptionIncludedPath> clientEncryptionIncludedPath)
private static void ValidateIncludedPaths(IEnumerable<ClientEncryptionIncludedPath> clientEncryptionIncludedPath, int policyFormatVersion)
{
List<string> includedPathsList = new List<string>();
foreach (ClientEncryptionIncludedPath path in clientEncryptionIncludedPath)
{
PSClientEncryptionPolicy.ValidateClientEncryptionIncludedPath(path);
PSClientEncryptionPolicy.ValidateClientEncryptionIncludedPath(path, policyFormatVersion);
if (includedPathsList.Contains(path.Path))
{
throw new ArgumentException($"Duplicate Path({path.Path}) found.", nameof(clientEncryptionIncludedPath));
Expand All @@ -131,7 +152,7 @@ private static void ValidateIncludedPaths(IEnumerable<ClientEncryptionIncludedPa
}
}

private static void ValidateClientEncryptionIncludedPath(ClientEncryptionIncludedPath clientEncryptionIncludedPath)
private static void ValidateClientEncryptionIncludedPath(ClientEncryptionIncludedPath clientEncryptionIncludedPath, int policyFormatVersion)
{
if (clientEncryptionIncludedPath == null)
{
Expand All @@ -144,8 +165,7 @@ private static void ValidateClientEncryptionIncludedPath(ClientEncryptionInclude
}

if (clientEncryptionIncludedPath.Path[0] != '/'
|| clientEncryptionIncludedPath.Path.LastIndexOf('/') != 0
|| string.Equals(clientEncryptionIncludedPath.Path.Substring(1), "id"))
|| clientEncryptionIncludedPath.Path.LastIndexOf('/') != 0)
{
throw new ArgumentException($"Invalid path '{clientEncryptionIncludedPath.Path ?? string.Empty}'.");
}
Expand All @@ -160,6 +180,19 @@ private static void ValidateClientEncryptionIncludedPath(ClientEncryptionInclude
throw new ArgumentNullException(nameof(clientEncryptionIncludedPath.EncryptionType));
}

if (string.Equals(clientEncryptionIncludedPath.Path.Substring(1), "id"))
{
if (policyFormatVersion < 2)
{
throw new ArgumentException($"Path: {clientEncryptionIncludedPath.Path} cannot be encrypted with PolicyFormatVersion: {policyFormatVersion}. Please use PolicyFormatVersion: 2. ");
}

if (clientEncryptionIncludedPath.EncryptionType != "Deterministic")
{
throw new ArgumentException($"Only Deterministic encryption type is supported for path: {clientEncryptionIncludedPath.Path}. ");
}
}

if (!string.Equals(clientEncryptionIncludedPath.EncryptionType, "Deterministic") &&
!string.Equals(clientEncryptionIncludedPath.EncryptionType, "Randomized"))
{
Expand Down
22 changes: 18 additions & 4 deletions src/CosmosDB/CosmosDB/Models/Sql/PSSqlClientEncryptionPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// limitations under the License.
// ----------------------------------------------------------------------------------
using Microsoft.Azure.Management.CosmosDB.Models;
using System;

namespace Microsoft.Azure.Commands.CosmosDB.Models
{
Expand All @@ -20,15 +21,28 @@ public class PSSqlClientEncryptionPolicy : PSClientEncryptionPolicy
{
public PSSqlClientEncryptionPolicy() : base()
{
}
}

public PSSqlClientEncryptionPolicy(ClientEncryptionPolicy clientEncryptionPolicy) : base(PSSqlClientEncryptionPolicy.SetSupportedPolicyVersionOnClientEncryptionPolicy(clientEncryptionPolicy))
public PSSqlClientEncryptionPolicy(ClientEncryptionPolicy clientEncryptionPolicy) : base(PSSqlClientEncryptionPolicy.SetSupportedPolicyVersionOnClientEncryptionPolicy(clientEncryptionPolicy, clientEncryptionPolicy.PolicyFormatVersion))
{
}

private static ClientEncryptionPolicy SetSupportedPolicyVersionOnClientEncryptionPolicy(ClientEncryptionPolicy clientEncryptionPolicy)
private static ClientEncryptionPolicy SetSupportedPolicyVersionOnClientEncryptionPolicy(ClientEncryptionPolicy clientEncryptionPolicy, int? policyFormatVersion = null)
{
clientEncryptionPolicy.PolicyFormatVersion = 1;
if (policyFormatVersion == null)
{
clientEncryptionPolicy.PolicyFormatVersion = 1;
}
else
{
if(policyFormatVersion > 2 || policyFormatVersion < 1)
{
throw new ArgumentException($"Supported versions of client encryption policy are 1 and 2. ");
}

clientEncryptionPolicy.PolicyFormatVersion = policyFormatVersion;
}

return clientEncryptionPolicy;
}
}
Expand Down
17 changes: 8 additions & 9 deletions src/CosmosDB/CosmosDB/help/New-AzCosmosDBSqlContainer.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,14 @@ Resource : Microsoft.Azure.Commands.CosmosDB.Models.PSSqlContainerGetPropertiesR

### Example 2: Create a new CosmosDB Sql Container with Client Encryption Policy
```powershell
$includedPath1 = [Microsoft.Azure.Management.CosmosDB.Models.ClientEncryptionIncludedPath]::new("/path1","key1","Deterministic","AEAD_AES_256_CBC_HMAC_SHA256");
$includedPath2 = [Microsoft.Azure.Management.CosmosDB.Models.ClientEncryptionIncludedPath]::new("/path2","key2","Randomized","AEAD_AES_256_CBC_HMAC_SHA256");
$listofIncludedPaths = New-Object Collections.Generic.List[Microsoft.Azure.Management.CosmosDB.Models.ClientEncryptionIncludedPath]
$listofIncludedPaths.Add($includedPath1)
$listofIncludedPaths.Add($includedPath2)
$newClientEncryptionPolicy = New-Object Microsoft.Azure.Management.CosmosDB.Models.ClientEncryptionPolicy
$newClientEncryptionPolicy.IncludedPaths = $listofIncludedPaths
$newPSSqlClientEncryptionPolicy = [Microsoft.Azure.Commands.CosmosDB.Models.PSSqlClientEncryptionPolicy]::new($newClientEncryptionPolicy)
New-AzCosmosDBSqlContainer -AccountName myAccountName -DatabaseName myDatabaseName -ResourceGroupName myRgName -Name myContainerName -PartitionKeyPath /a/b/c -PartitionKeyKind Hash -ClientEncryptionPolicy $newPSSqlClientEncryptionPolicy
PS C:\> $includedPath1 = [Microsoft.Azure.Management.CosmosDB.Models.ClientEncryptionIncludedPath]::new("/path1","key1","Deterministic","AEAD_AES_256_CBC_HMAC_SHA256");
PS C:\> $includedPath2 = [Microsoft.Azure.Management.CosmosDB.Models.ClientEncryptionIncludedPath]::new("/path2","key2","Randomized","AEAD_AES_256_CBC_HMAC_SHA256");
PS C:\> $listofIncludedPaths = New-Object Collections.Generic.List[Microsoft.Azure.Management.CosmosDB.Models.ClientEncryptionIncludedPath]
PS C:\> $listofIncludedPaths.Add($includedPath1)
PS C:\> $listofIncludedPaths.Add($includedPath2)
PS C:\> $newClientEncryptionPolicy = [Microsoft.Azure.Management.CosmosDB.Models.ClientEncryptionPolicy]::new($listofIncludedPaths, 2)
PS C:\> $newPSSqlClientEncryptionPolicy = [Microsoft.Azure.Commands.CosmosDB.Models.PSSqlClientEncryptionPolicy]::new($newClientEncryptionPolicy)
PS C:\> New-AzCosmosDBSqlContainer -AccountName myAccountName -DatabaseName myDatabaseName -ResourceGroupName myRgName -Name myContainerName -PartitionKeyPath /a/b/c -PartitionKeyKind Hash -ClientEncryptionPolicy $newPSSqlClientEncryptionPolicy
```

```output
Expand Down