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 fix to allow partition key path and id to be part of client encryption policy. #30678

Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
3b58257
Initial commit
aayush3011 Aug 28, 2022
3cdc355
Updated changelog
aayush3011 Aug 28, 2022
a043812
Fixing spot bugs
aayush3011 Aug 28, 2022
860885b
Resolving comments
aayush3011 Sep 26, 2022
b3766a3
Merge branch 'Azure:main' into users/akataria/EncryptionPartitionKeyPath
aayush3011 Sep 26, 2022
c101882
Merge branch 'Azure:main' into users/akataria/EncryptionPartitionKeyPath
aayush3011 Oct 31, 2022
c24a480
Fixing CI build
aayush3011 Oct 31, 2022
337b94c
Fixing CI build
aayush3011 Oct 31, 2022
dd159b3
Added code to allow encryption of partitionKey and id
aayush3011 Nov 2, 2022
56b18cf
removing unused imports
aayush3011 Nov 2, 2022
06ed153
Fixing CI build
aayush3011 Nov 2, 2022
e8a16fc
Adding test cases
aayush3011 Nov 2, 2022
65069b8
Fixing change log
aayush3011 Nov 2, 2022
98a86a9
Resolving comments
aayush3011 Nov 2, 2022
8e67cb0
Fixing builds
aayush3011 Nov 2, 2022
1cd45bf
Resolving comments
aayush3011 Nov 2, 2022
22ad6c9
Fixing test cases
aayush3011 Nov 2, 2022
13d3282
FIxing builds
aayush3011 Nov 15, 2022
fe789db
Fixing versioning
aayush3011 Nov 15, 2022
2726c49
Merge branch 'main' into users/akataria/EncryptionPartitionKeyPath
aayush3011 Nov 15, 2022
03bf1bb
Resolving commentsg
aayush3011 Nov 15, 2022
c7db2d9
Merge branch 'users/akataria/EncryptionPartitionKeyPath' of github.co…
aayush3011 Nov 15, 2022
a1bfcce
Resolving commentsg
aayush3011 Nov 15, 2022
5e0158d
Merge branch 'Azure:main' into users/akataria/EncryptionPartitionKeyPath
aayush3011 Nov 15, 2022
3c6c807
Fixing versioning
aayush3011 Nov 15, 2022
3669287
Resolving comments
aayush3011 Nov 15, 2022
598b675
Fixing builds
aayush3011 Nov 15, 2022
6f81259
Fixing spotbugs
aayush3011 Nov 15, 2022
e555b03
Fixing spotbugs
aayush3011 Nov 15, 2022
f9f293d
Fixing builds
aayush3011 Nov 16, 2022
9613939
Fixing test cases
aayush3011 Nov 16, 2022
a071e8d
Fixing test cases
aayush3011 Nov 16, 2022
921f156
Fixing test cases
aayush3011 Nov 17, 2022
ee10fd7
Merge branch 'main' into users/akataria/EncryptionPartitionKeyPath
aayush3011 Nov 17, 2022
3522fc8
Fixing test cases
aayush3011 Nov 17, 2022
a23d43d
Fixing test cases
aayush3011 Feb 16, 2023
bcd030a
Fixing test cases
aayush3011 Feb 21, 2023
6017f35
Merge branch 'main' into users/akataria/EncryptionPartitionKeyPath
aayush3011 Feb 21, 2023
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
2 changes: 2 additions & 0 deletions sdk/cosmos/azure-cosmos-encryption/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
### 1.6.0-beta.1 (Unreleased)
aayush3011 marked this conversation as resolved.
Show resolved Hide resolved

#### Features Added
* Added support for allowing parition key path and id to be part of client encryption policy - See [PR 30678](https://github.com/Azure/azure-sdk-for-java/pull/30678)


#### Breaking Changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,25 @@ public final class ClientEncryptionPolicy {
*/
@Beta(value = Beta.SinceVersion.V4_14_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING)
public ClientEncryptionPolicy(List<ClientEncryptionIncludedPath> paths) {
this.validateIncludedPaths(paths);
this.includedPaths = paths;
this.policyFormatVersion = 1;
this.validateIncludedPaths(paths, policyFormatVersion);
this.includedPaths = paths;
}

/**
* Constructor.
*
* @param paths list of path of the item that need encryption along with path-specific settings.
* @param policyFormatVersion version of the client encryption policy definition. Current supported versions are 1 and 2. Default version is 1.
aayush3011 marked this conversation as resolved.
Show resolved Hide resolved
*/
@Beta(value = Beta.SinceVersion.V4_14_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING)
public ClientEncryptionPolicy(List<ClientEncryptionIncludedPath> paths, int policyFormatVersion) {
if (policyFormatVersion > 2 || policyFormatVersion < 1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make policyFormatVersion immutable (so that it is initialized only once per ClientEncryptionPolicy).

throw new IllegalArgumentException("Supported versions of client encryption policy are 1 and 2.");
}
this.policyFormatVersion = policyFormatVersion;
this.validateIncludedPaths(paths, policyFormatVersion);
aayush3011 marked this conversation as resolved.
Show resolved Hide resolved
this.includedPaths = paths;
}

/**
Expand Down Expand Up @@ -71,7 +87,7 @@ public ClientEncryptionPolicy() {
}

/**
* Gets the list of path of the item that need encryption along with path-specific settings.
* Gets the list of paths of the item that need encryption along with path-specific settings.
* @return includedPaths
*/
@Beta(value = Beta.SinceVersion.V4_11_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING)
Expand All @@ -88,28 +104,44 @@ public int getPolicyFormatVersion() {
return policyFormatVersion;
}

void validatePartitionKeyPathsAreNotEncrypted(List<List<String>> partitionKeyPathTokens) {
/**
* Ensures that partition key paths specified in the client encryption policy for encryption are encrypted using Deterministic encryption algorithm.
* @param partitionKeyPathTokens Tokens corresponding to validated partition key.
*/
void validatePartitionKeyPathsIfEncrypted(List<List<String>> partitionKeyPathTokens) {
checkNotNull(partitionKeyPathTokens, "partitionKeyPathTokens cannot be null");
List<String> propertiesToEncrypt =
this.includedPaths.stream().map(clientEncryptionIncludedPath -> clientEncryptionIncludedPath.getPath().substring(1)).collect(Collectors.toList());


for (List<String> tokensInPath : partitionKeyPathTokens) {
checkNotNull(tokensInPath);
if (tokensInPath.size() > 0) {
String topLevelToken = tokensInPath.get(0);
if (propertiesToEncrypt.contains(topLevelToken)) {

// paths in included paths start with "/". Get the ClientEncryptionIncludedPath and validate.
List<ClientEncryptionIncludedPath> encrypterPartitionKeyPath =
this.includedPaths.stream().filter(clientEncryptionIncludedPath -> clientEncryptionIncludedPath.getPath().substring(1).equals(topLevelToken)).collect(Collectors.toList());

if (encrypterPartitionKeyPath.size() >0) {
if (this.policyFormatVersion < 2) {
throw new IllegalArgumentException(String.format("Path %s which is part of the partition key " +
"cannot be encrypted" +
" with PolicyFormatVersion %s", topLevelToken, policyFormatVersion));
}

// for the ClientEncryptionIncludedPath found check the encryption type.
if (!encrypterPartitionKeyPath.stream().map(encrypter -> encrypter.getEncryptionType()).findFirst().orElse(null).equals("Deterministic"))
aayush3011 marked this conversation as resolved.
Show resolved Hide resolved
aayush3011 marked this conversation as resolved.
Show resolved Hide resolved
throw new IllegalArgumentException(String.format("Path %s which is part of the partition key " +
"cannot be included" +
" in the ClientEncryptionPolicy.", topLevelToken));
"has to be encrypted" +
" with Deterministic type Encryption.", topLevelToken));
}
}
}
}

private void validateIncludedPaths(List<ClientEncryptionIncludedPath> clientEncryptionIncludedPath) {
private void validateIncludedPaths(List<ClientEncryptionIncludedPath> clientEncryptionIncludedPath, int policyFormatVersion) {
List<String> includedPathsList = new ArrayList<>();
for (ClientEncryptionIncludedPath path : clientEncryptionIncludedPath) {
this.validateClientEncryptionIncludedPath(path);
this.validateClientEncryptionIncludedPath(path, policyFormatVersion);
if (includedPathsList.contains(path.getPath())) {
throw new IllegalArgumentException("Duplicate Path found in clientEncryptionIncludedPath.");
}
Expand All @@ -118,7 +150,7 @@ private void validateIncludedPaths(List<ClientEncryptionIncludedPath> clientEncr
}
}

private void validateClientEncryptionIncludedPath(ClientEncryptionIncludedPath clientEncryptionIncludedPath) {
private void validateClientEncryptionIncludedPath(ClientEncryptionIncludedPath clientEncryptionIncludedPath, int policyFormatVersion) {
if (clientEncryptionIncludedPath == null) {
throw new IllegalArgumentException("clientEncryptionIncludedPath is null");
}
Expand All @@ -128,11 +160,20 @@ private void validateClientEncryptionIncludedPath(ClientEncryptionIncludedPath c
}

if (clientEncryptionIncludedPath.getPath().charAt(0) != '/'
|| clientEncryptionIncludedPath.getPath().lastIndexOf('/') != 0
|| clientEncryptionIncludedPath.getPath().substring(1).equals("id")) {
|| clientEncryptionIncludedPath.getPath().lastIndexOf('/') != 0) {
throw new IllegalArgumentException("Invalid path " + clientEncryptionIncludedPath.getPath());
}

if (clientEncryptionIncludedPath.getPath().substring(1).equals("id")) {
if (policyFormatVersion < 2) {
throw new IllegalArgumentException(String.format("Path %s cannot be encrypted with policyFormatVersion %s.", clientEncryptionIncludedPath.getPath(), policyFormatVersion));
}

if (!clientEncryptionIncludedPath.getEncryptionType().equals("Deterministic")) {
aayush3011 marked this conversation as resolved.
Show resolved Hide resolved
throw new IllegalArgumentException(String.format("Only deterministic encryption type is supported for path %s.", clientEncryptionIncludedPath.getPath()));
}
}

if (StringUtils.isEmpty(clientEncryptionIncludedPath.getClientEncryptionKeyId())) {
throw new IllegalArgumentException("clientEncryptionKeyId in clientEncryptionIncludedPath is empty");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public PartitionKeyDefinition getPartitionKeyDefinition() {
public CosmosContainerProperties setPartitionKeyDefinition(PartitionKeyDefinition partitionKeyDefinition) {
this.documentCollection.setPartitionKey(partitionKeyDefinition);
if (this.getClientEncryptionPolicy() != null) {
this.getClientEncryptionPolicy().validatePartitionKeyPathsAreNotEncrypted(this.getPartitionKeyPathTokensList());
this.getClientEncryptionPolicy().validatePartitionKeyPathsIfEncrypted(this.getPartitionKeyPathTokensList());
}

return this;
Expand Down Expand Up @@ -317,7 +317,7 @@ public ClientEncryptionPolicy getClientEncryptionPolicy() {
@Beta(value = Beta.SinceVersion.V4_14_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING)
public CosmosContainerProperties setClientEncryptionPolicy(ClientEncryptionPolicy value) {
if (value != null) {
value.validatePartitionKeyPathsAreNotEncrypted(this.getPartitionKeyPathTokensList());
value.validatePartitionKeyPathsIfEncrypted(this.getPartitionKeyPathTokensList());
}

this.documentCollection.setClientEncryptionPolicy(value);
Expand Down
Loading