Skip to content

Conversation

@akareddy04
Copy link
Contributor

Issue #, if available:

Description of changes:
Added configuration of MaterialsDescription for Keyrings

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Check any applicable:

  • Were any files moved? Moving files changes their URL, which breaks all hyperlinks to the files.

Anirav Kareddy added 4 commits June 17, 2025 11:24
…eys for reEncryptInstructionFile feature. I also included simple test cases to verify that the builder for the MaterialsDescription class is working as well as validation checks to ensure that MaterialsDescription is provided in the case that reEncryptInstructionFile is true
@akareddy04 akareddy04 requested a review from a team as a code owner June 17, 2025 21:04
Copy link
Contributor

@kessplas kessplas left a comment

Choose a reason for hiding this comment

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

Either in this PR, or in a follow up, we need to add this to the ContentMetadata such that it gets written to object metadata/instruction file on PutObject and also returned on GetObject. We need to this before implementing the reEncrypt API as it can't work without the MatDesc actually being present in the metadata.

* This will be useful during re-encryption of instruction file.
* The stored Materials Description are immutable once created.
*/

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change

import java.util.HashMap;
import java.util.Map;
/**
* This class is used to store and manage key-value pairs that describe keyring,specifically for AES and RSA Keyring.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* This class is used to store and manage key-value pairs that describe keyring,specifically for AES and RSA Keyring.
* This class is used to provide key-value pairs that describe key material used with the Keyring, specifically for AES and RSA Keyrings.

public static Builder builder() {
return new Builder();
}
public Map<String, String> getDescription() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public Map<String, String> getDescription() {
public Map<String, String> getMaterialsDescription() {

_wrappingKey = wrappingKey;
return builder();
}
public Builder reEncryptInstructionFile(boolean reEncryptInstructionFile) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Discussed offline: since the "from" keyring can have a null matdesc, we can't enforce this check until the reEncrypt API is called, so we'll need to remove this.

assertEquals(1, materialsDescription.getDescription().size());
try {
materialsDescription.getDescription().put("version", "2.0");
throw new RuntimeException("Expected UnsupportedOperationException");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
throw new RuntimeException("Expected UnsupportedOperationException");
fail("Expected UnsupportedOperationException");

* The stored Materials Description are immutable once created.
*/

public class MaterialsDescription {
Copy link
Contributor

Choose a reason for hiding this comment

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

We can have this be a Map<String, String> extension, meaning:

implements Map<String, String>

We'll need to implement a bunch of other methods, but they can all be deferred to the "inner" map pretty easily. This is a nicer customer experience as customers can use all of the usual Map API and aren't limited to the things we chose to implement.

Anirav Kareddy added 23 commits June 18, 2025 14:41
…RSA Keyrings will extend from and I also moved the warnIfEncryptionContextIsPresent() method from S3Keyring to RawKeyring since the method really only targets AES + RSA keyrings which will extend this class
…extending the abstract builder from RawKeyring
… transferred it over to RawKeyring class which AES + RSA extend from (note: this method is only for AES + RSA Keyrings)
…ill already be inherited from RawKeyring class
…nt MaterialsDescription (note: MaterialsDescription and Encryption Context are stored in the same field, but you will never have both at the same time (one of them will always be empty
…context and materials description will be treated as different
…DataKeyContext to _encryptionContextOrMatDesc bc in V2 both encryption context and materials description were treated the same (backwards compatability)
…tion Materials in putObject by first creating a helper method in the RawKeyring class that both AES + RSA keyrings will call in the override modifyMaterials method to return materials description instead of empty encryption materials
jsonWriter.writeStartObject();
for (Map.Entry<String, String> entry : materials.encryptionContext().entrySet()) {
jsonWriter.writeFieldName(entry.getKey()).writeValue(entry.getValue());
if (!materials.encryptionContext().isEmpty() && materials.materialsDescription().isEmpty()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should add a test which passes both a MatDesc on keyring initialization and an EC on PutObject for AES and RSA keyrings. While this is not a good idea (the EC will be dropped and a warning will be logged) we should add a test to make sure that we store the MatDesc and not the EC.

AesKeyring aesKeyring = AesKeyring.builder()
.wrappingKey(AES_KEY)
.reEncryptInstructionFile(true)
.secureRandom(new SecureRandom())
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: this is superfluous

.keyring(aesKeyring)
.build();
final String input = "Testing Materials Description in Object Metadata!";
final String objectKey = "test-aes-materials-description-in-object-metadata";
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
final String objectKey = "test-aes-materials-description-in-object-metadata";
final String objectKey = appendTestSuffix("test-aes-materials-description-in-object-metadata");

.key(objectKey)
.build());
assertEquals(input, responseBytes.asUtf8String());
assertEquals("{\"admin\":\"yes\",\"version\":\"1.0\"}", responseBytes.response().metadata().get("x-amz-matdesc"));
Copy link
Contributor

Choose a reason for hiding this comment

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

This is fine for one key, but I'd prefer using a parser here, as I'm not sure if the order is guaranteed.

.build();

final String input = "Testing Materials Description in Instruction File!";
final String objectKey = "test-rsa-materials-description-in-instruction-file";
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto appendTestSuffix (here and everywhere else)

Copy link
Contributor

@kessplas kessplas left a comment

Choose a reason for hiding this comment

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

See comment about Encryption Context

Comment on lines 275 to 276
.serverSideEncryption(ServerSideEncryption.AWS_KMS)
.ssekmsEncryptionContext(Base64.getEncoder().encodeToString(encryptionContext.getBytes(StandardCharsets.UTF_8)))
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not how EncryptionContext is passed to S3EC.

Refer to e.g. KmsContextV2toV3 in the compatibility tests for an example of S3EC EncryptionContext.

Comment on lines 321 to 322
.serverSideEncryption(ServerSideEncryption.AWS_KMS)
.ssekmsEncryptionContext(Base64.getEncoder().encodeToString(encryptionContext.getBytes(StandardCharsets.UTF_8)))
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto

}

@Test
public void testMaterialsDescriptionRsaKeyring() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This test and the one above it should be moved to the unit test class (MaterialsDescriptionTest)

Copy link
Contributor

@kessplas kessplas left a comment

Choose a reason for hiding this comment

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

LGTM!

@akareddy04 akareddy04 merged commit b643bc8 into aniravk/ReEncrypt-feature Jun 25, 2025
30 of 35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants