diff --git a/src/CosmosDB/CosmosDB/ChangeLog.md b/src/CosmosDB/CosmosDB/ChangeLog.md index 891a1072678d..adb00f14b1a6 100644 --- a/src/CosmosDB/CosmosDB/ChangeLog.md +++ b/src/CosmosDB/CosmosDB/ChangeLog.md @@ -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 diff --git a/src/CosmosDB/CosmosDB/Models/PSClientEncryptionPolicy.cs b/src/CosmosDB/CosmosDB/Models/PSClientEncryptionPolicy.cs index 2063716d1dd7..8b16c1531170 100644 --- a/src/CosmosDB/CosmosDB/Models/PSClientEncryptionPolicy.cs +++ b/src/CosmosDB/CosmosDB/Models/PSClientEncryptionPolicy.cs @@ -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(); foreach (ClientEncryptionIncludedPath key in clientEncryptionPolicy.IncludedPaths) @@ -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. "); } @@ -102,26 +105,44 @@ public static ClientEncryptionPolicy ToSDKModel(PSClientEncryptionPolicy pSClien /// /// Included paths of the client encryption policy. /// Tokens corresponding to validated partition key. - private static void ValidatePartitionKeyPathsAreNotEncrypted(IEnumerable clientEncryptionIncludedPath, List partitionKeyPathTokens) + /// Client encryption policy format version. + private static void ValidatePartitionKeyPathsAreNotEncrypted( + IEnumerable clientEncryptionIncludedPath, + List partitionKeyPathTokens, + int policyFormatVersion) { Debug.Assert(partitionKeyPathTokens != null); - IEnumerable 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 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) + private static void ValidateIncludedPaths(IEnumerable clientEncryptionIncludedPath, int policyFormatVersion) { List includedPathsList = new List(); 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)); @@ -131,7 +152,7 @@ private static void ValidateIncludedPaths(IEnumerable 2 || policyFormatVersion < 1) + { + throw new ArgumentException($"Supported versions of client encryption policy are 1 and 2. "); + } + + clientEncryptionPolicy.PolicyFormatVersion = policyFormatVersion; + } + return clientEncryptionPolicy; } } diff --git a/src/CosmosDB/CosmosDB/help/New-AzCosmosDBSqlContainer.md b/src/CosmosDB/CosmosDB/help/New-AzCosmosDBSqlContainer.md index 27205b3b4d9c..69bbbd9cce5c 100644 --- a/src/CosmosDB/CosmosDB/help/New-AzCosmosDBSqlContainer.md +++ b/src/CosmosDB/CosmosDB/help/New-AzCosmosDBSqlContainer.md @@ -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