Skip to content

Commit d4cef6e

Browse files
author
Anirav Kareddy
committed
Added javadoc comments for readability
1 parent d45c026 commit d4cef6e

File tree

4 files changed

+131
-6
lines changed

4 files changed

+131
-6
lines changed

src/main/java/software/amazon/encryption/s3/S3EncryptionClient.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979
import java.security.Provider;
8080
import java.security.SecureRandom;
8181
import java.util.ArrayList;
82-
import java.util.Arrays;
8382
import java.util.Collections;
8483
import java.util.List;
8584
import java.util.Map;
@@ -109,6 +108,7 @@ public class S3EncryptionClient extends DelegatingS3Client {
109108
public static final ExecutionAttribute<Map<String, String>> ENCRYPTION_CONTEXT = new ExecutionAttribute<>("EncryptionContext");
110109
public static final ExecutionAttribute<MultipartConfiguration> CONFIGURATION = new ExecutionAttribute<>("MultipartConfiguration");
111110

111+
//Used for specifying custom instruction file suffix on a per-request basis
112112
public static final ExecutionAttribute<String> CUSTOM_INSTRUCTION_FILE_SUFFIX = new ExecutionAttribute<>("CustomInstructionFileSuffix");
113113

114114
private final S3Client _wrappedClient;
@@ -157,6 +157,13 @@ public static Consumer<AwsRequestOverrideConfiguration.Builder> withAdditionalCo
157157
builder.putExecutionAttribute(S3EncryptionClient.ENCRYPTION_CONTEXT, encryptionContext);
158158
}
159159

160+
/**
161+
* Attaches a custom instruction file suffix to a request. Must be used as a parameter to
162+
* {@link S3Request#overrideConfiguration()} in the request.
163+
* This allows specifying a custom suffix for the instruction file on a per-request basis.
164+
* @param customInstructionFileSuffix the custom suffix to use for the instruction file.
165+
* @return Consumer for use in overrideConfiguration()
166+
*/
160167
public static Consumer<AwsRequestOverrideConfiguration.Builder> withCustomInstructionFileSuffix(String customInstructionFileSuffix) {
161168
return builder ->
162169
builder.putExecutionAttribute(S3EncryptionClient.CUSTOM_INSTRUCTION_FILE_SUFFIX, customInstructionFileSuffix);
@@ -190,6 +197,29 @@ public static Consumer<AwsRequestOverrideConfiguration.Builder> withAdditionalCo
190197
.putExecutionAttribute(S3EncryptionClient.CONFIGURATION, multipartConfiguration);
191198
}
192199

200+
/**
201+
* Re-encrypts an instruction file with a new keyring while preserving the original encrypted object in S3.
202+
* This enables:
203+
* 1. Key rotation by updating instruction file metadata without re-encrypting object content
204+
* 2. Sharing encrypted objects with partners by creating new instruction files with their public keys
205+
* <p>
206+
* Key rotation scenarios:
207+
* - Legacy to V3: Can rotate same key type from V1/V2 to V3's improved algorithms
208+
* - Within V3: Cannot rotate to same key (must use different keyring)
209+
* <p>
210+
* Instruction file behavior:
211+
* - AES keyrings: Uses default ".instruction" suffix
212+
* - RSA keyrings: Requires custom suffix for multiple access patterns
213+
* <p>
214+
* Requirements:
215+
* - New keyring must have different materials description
216+
* - Custom instruction file suffix required for RSA keyrings
217+
* - Default instruction file suffix required for AES keyrings
218+
*
219+
* @param reEncryptInstructionFileRequest the request containing bucket, object key, new keyring, and optional instruction file suffix
220+
* @return ReEncryptInstructionFileResponse containing the bucket, object key, and instruction file suffix used
221+
* @throws S3EncryptionClientException if the new keyring has the same materials description as the current one
222+
*/
193223
public ReEncryptInstructionFileResponse reEncryptInstructionFile(ReEncryptInstructionFileRequest reEncryptInstructionFileRequest) {
194224
GetObjectRequest request = GetObjectRequest.builder()
195225
.bucket(reEncryptInstructionFileRequest.bucket())
@@ -224,7 +254,7 @@ public ReEncryptInstructionFileResponse reEncryptInstructionFile(ReEncryptInstru
224254
EncryptionMaterials encryptedMaterials = newKeyring.onEncrypt(encryptionMaterials);
225255

226256
if (encryptedMaterials.materialsDescription().equals(currentKeyringMaterialsDescription)) {
227-
throw new S3EncryptionClientException("New keyring must generate new materials description!");
257+
throw new S3EncryptionClientException("New keyring must have new materials description!");
228258
}
229259

230260
ContentMetadataEncodingStrategy encodeStrategy = new ContentMetadataEncodingStrategy(_instructionFileConfig);

src/main/java/software/amazon/encryption/s3/internal/ReEncryptInstructionFileRequest.java

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
import software.amazon.encryption.s3.materials.RawKeyring;
88
import software.amazon.encryption.s3.materials.RsaKeyring;
99

10-
/** Request object for re-encrypting instruction files.
11-
* Supports both AES and RSA keyring with different instruction file suffixes.
10+
/**
11+
* Request object for re-encrypting instruction files in S3.
12+
* This request supports re-encryption operations using either AES or RSA keyrings.
13+
* For AES keyrings, only the default instruction file suffix is supported.
14+
* For RSA keyrings, a custom instruction file suffix must be provided to support
15+
* multiple accesses to the same encrypted object.
1216
*/
1317
public class ReEncryptInstructionFileRequest {
1418
private final String bucket;
@@ -23,53 +27,106 @@ private ReEncryptInstructionFileRequest(Builder builder) {
2327
instructionFileSuffix = builder.instructionFileSuffix;
2428
}
2529

30+
/**
31+
* @return the S3 bucket name that contains the encrypted object and instruction file to re-encrypt
32+
*/
2633
public String bucket() {
2734
return bucket;
2835
}
2936

37+
/**
38+
* @return the S3 object key of the encrypted object whose instruction file will be re-encrypted
39+
*/
3040
public String key() {
3141
return key;
3242
}
3343

44+
/**
45+
* @return the new keyring (AES or RSA) that will be used to re-encrypt the instruction file
46+
*/
3447
public RawKeyring newKeyring() {
3548
return newKeyring;
3649
}
3750

51+
/**
52+
* @return the suffix to use for the instruction file. The default instruction file suffix is ".instruction" for
53+
* AES keyrings and the instruction file suffix must be different from the default one for RSA keyrings
54+
*/
3855
public String instructionFileSuffix() {
3956
return instructionFileSuffix;
4057
}
4158

59+
/**
60+
* Creates a builder that can be used to configure and create a {@link ReEncryptInstructionFileRequest}
61+
*
62+
* @return a new builder
63+
*/
4264
public static Builder builder() {
4365
return new Builder();
4466
}
4567

68+
/**
69+
* Builder for ReEncryptInstructionFileRequest.
70+
*/
4671
public static class Builder {
4772
private static final String DEFAULT_INSTRUCTION_FILE_SUFFIX = ".instruction";
4873
private String bucket;
4974
private String key;
5075
private RawKeyring newKeyring;
5176
private String instructionFileSuffix = DEFAULT_INSTRUCTION_FILE_SUFFIX;
5277

78+
/**
79+
* Sets the S3 bucket name for the re-encryption of instruction file.
80+
*
81+
* @param bucket the S3 bucket name
82+
* @return a reference to this object so that method calls can be chained together.
83+
*/
5384
public Builder bucket(String bucket) {
5485
this.bucket = bucket;
5586
return this;
5687
}
5788

89+
/**
90+
* Sets the S3 object key for the re-encryption of instruction file.
91+
*
92+
* @param key the S3 object key
93+
* @return a reference to this object so that method calls can be chained together.
94+
*/
5895
public Builder key(String key) {
5996
this.key = key;
6097
return this;
6198
}
6299

100+
/**
101+
* Sets the new keyring for re-encryption of instruction file.
102+
*
103+
* @param newKeyring the new keyring for re-encryption
104+
* @return a reference to this object so that method calls can be chained together.
105+
*/
63106
public Builder newKeyring(RawKeyring newKeyring) {
64107
this.newKeyring = newKeyring;
65108
return this;
66109
}
67110

111+
/**
112+
* Sets a custom instruction file suffix for the re-encrypted instruction file.
113+
* For AES keyrings, only the default instruction file suffix is allowed.
114+
* For RSA keyrings, a custom suffix different from the default must be provided.
115+
*
116+
* @param instructionFileSuffix the instruction file suffix
117+
* @return a reference to this object so that method calls can be chained together.
118+
*/
68119
public Builder instructionFileSuffix(String instructionFileSuffix) {
69120
this.instructionFileSuffix = "." + instructionFileSuffix;
70121
return this;
71122
}
72123

124+
/**
125+
* Validates and builds the ReEncryptInstructionFileRequest according
126+
* to the configuration options passed to the Builder object.
127+
*
128+
* @return an instance of the ReEncryptInstructionFileRequest
129+
*/
73130
public ReEncryptInstructionFileRequest build() {
74131
if (bucket == null || bucket.isEmpty()) {
75132
throw new S3EncryptionClientException("Bucket must be provided!");

src/main/java/software/amazon/encryption/s3/internal/ReEncryptInstructionFileResponse.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,45 @@
22
// SPDX-License-Identifier: Apache-2.0
33
package software.amazon.encryption.s3.internal;
44

5-
/** Response object for re-encrypting instruction files.
6-
* Contains the bucket, key, and instruction file suffix of the re-encrypted instruction file in S3.
5+
/**
6+
* Response object returned after re-encrypting an instruction file in S3.
7+
* Contains the S3 bucket name, object key, and instruction file suffix used for the re-encrypted instruction file
78
*/
89
public class ReEncryptInstructionFileResponse {
910
private final String bucket;
1011
private final String key;
1112
private final String instructionFileSuffix;
1213

14+
/**
15+
* Creates a new ReEncryptInstructionFileResponse object with the specified parameters.
16+
*
17+
* @param bucket the S3 bucket containing the re-encrypted instruction file
18+
* @param key the S3 object key of the encrypted object in S3
19+
* @param instructionFileSuffix the suffix used for the instruction file
20+
*/
1321
public ReEncryptInstructionFileResponse(String bucket, String key, String instructionFileSuffix) {
1422
this.bucket = bucket;
1523
this.key = key;
1624
this.instructionFileSuffix = instructionFileSuffix;
1725
}
1826

27+
/**
28+
* @return the S3 bucket containing the re-encrypted instruction file
29+
*/
1930
public String Bucket() {
2031
return bucket;
2132
}
2233

34+
/**
35+
* @return the S3 object key of the encrypted object in S3
36+
*/
2337
public String Key() {
2438
return key;
2539
}
2640

41+
/**
42+
* @return the instruction file suffix used for the instruction file
43+
*/
2744
public String InstructionFileSuffix() {
2845
return instructionFileSuffix;
2946
}

src/main/java/software/amazon/encryption/s3/materials/RawKeyring.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ protected RawKeyring(Builder<?, ?> builder) {
1616
_materialsDescription = builder._materialsDescription;
1717
}
1818

19+
/**
20+
* Modifies encryption materials with the keyring's materials description if present.
21+
* Issues a warning if encryption context is found, as it provides no security benefit for raw keyrings.
22+
*
23+
* @param materials the encryption materials to modify
24+
* @return modified encryption materials with the keyring's materials description or original encryption materials if no materials description is set
25+
*/
1926
public EncryptionMaterials modifyMaterialsForRawKeyring(EncryptionMaterials materials) {
2027
warnIfEncryptionContextIsPresent(materials);
2128
if (_materialsDescription != null && !_materialsDescription.isEmpty()) {
@@ -46,6 +53,13 @@ public void warnIfEncryptionContextIsPresent(EncryptionMaterials materials) {
4653
"stored in the material description. Provide a MaterialDescription in the Keyring's builder instead."));
4754
}
4855

56+
/**
57+
* Abstract builder for RawKeyring implementations.
58+
* Provides common functionality for setting materials description on raw keyrings.
59+
*
60+
* @param <KeyringT> the type of keyring being built
61+
* @param <BuilderT> the type of builder
62+
*/
4963
public static abstract class Builder<KeyringT extends RawKeyring, BuilderT extends Builder<KeyringT, BuilderT>>
5064
extends S3Keyring.Builder<KeyringT, BuilderT> {
5165

@@ -55,6 +69,13 @@ protected Builder() {
5569
super();
5670
}
5771

72+
/**
73+
* Sets the materials description for this keyring.
74+
* Materials description provides additional metadata for raw keyrings.
75+
*
76+
* @param materialsDescription the materials description to associate with this keyring.
77+
* @return a reference to this object so that method calls can be chained together.
78+
*/
5879
public BuilderT materialsDescription(MaterialsDescription materialsDescription) {
5980
_materialsDescription = materialsDescription;
6081
return builder();

0 commit comments

Comments
 (0)