Skip to content

Commit 72784e0

Browse files
authored
Merge branch 'main' into multiple-raw-keys
2 parents ec5887e + ab41a57 commit 72784e0

File tree

9 files changed

+232
-32
lines changed

9 files changed

+232
-32
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ duvet_report:
1111
report \
1212
--spec-pattern "compliance/**/*.toml" \
1313
--source-pattern "src/**/*.java" \
14+
--source-pattern "compliance_exceptions/*.txt" \
1415
--html specification_compliance_report.html
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// The KMS Keyring in S3EC Java v3 does not validate KMS Key IDs.
2+
// Passing an invalid key ID will eventually lead to KMS Request failures.
3+
4+
//= specification/s3-encryption/materials/s3-kms-keyring.md#initialization
5+
//= type=exception
6+
//# The KmsKeyring MAY validate that the AWS KMS key identifier is not null or empty.
7+
//= specification/s3-encryption/materials/s3-kms-keyring.md#initialization
8+
//= type=exception
9+
//# If the KmsKeyring validates that the AWS KMS key identifier is not null or empty, then it MUST throw an exception.
10+
//= specification/s3-encryption/materials/s3-kms-keyring.md#initialization
11+
//= type=exception
12+
//# The KmsKeyring MAY validate that the AWS KMS key identifier is [a valid AWS KMS Key identifier](../../framework/aws-kms/aws-kms-key-arn.md#a-valid-aws-kms-identifier).
13+
//= specification/s3-encryption/materials/s3-kms-keyring.md#initialization
14+
//= type=exception
15+
//# If the KmsKeyring validates that the AWS KMS key identifier is not a valid AWS KMS Key identifier, then it MUST throw an exception.

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

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public static Consumer<AwsRequestOverrideConfiguration.Builder> withAdditionalCo
213213

214214
//= specification/s3-encryption/client.md#optional-api-operations
215215
//= type=implication
216-
//# ReEncryptInstructionFile MAY be implemented by the S3EC.
216+
//# - ReEncryptInstructionFile MAY be implemented by the S3EC.
217217
/**
218218
* Re-encrypts an instruction file with a new keyring while preserving the original encrypted object in S3.
219219
* This enables:
@@ -253,7 +253,7 @@ public ReEncryptInstructionFileResponse reEncryptInstructionFile(ReEncryptInstru
253253
//Decrypt the data key using the current keyring
254254
//= specification/s3-encryption/client.md#optional-api-operations
255255
//= type=implication
256-
//# ReEncryptInstructionFile MUST decrypt the instruction file's encrypted data key for the given object using the client's CMM.
256+
//# - ReEncryptInstructionFile MUST decrypt the instruction file's encrypted data key for the given object using the client's CMM.
257257
DecryptionMaterials decryptedMaterials = this._cryptoMaterialsManager.decryptMaterials(
258258
DecryptMaterialsRequest.builder()
259259
.algorithmSuite(algorithmSuite)
@@ -275,7 +275,7 @@ public ReEncryptInstructionFileResponse reEncryptInstructionFile(ReEncryptInstru
275275
//Re-encrypt the data key with the new keyring while preserving other cryptographic parameters
276276
//= specification/s3-encryption/client.md#optional-api-operations
277277
//= type=implication
278-
//# ReEncryptInstructionFile MUST re-encrypt the plaintext data key with a provided keyring.
278+
//# - ReEncryptInstructionFile MUST re-encrypt the plaintext data key with a provided keyring.
279279
RawKeyring newKeyring = reEncryptInstructionFileRequest.newKeyring();
280280
EncryptionMaterials encryptedMaterials = newKeyring.onEncrypt(encryptionMaterials);
281281

@@ -319,7 +319,7 @@ private void enforceRotation(EncryptionMaterials newEncryptionMaterials, GetObje
319319

320320
//= specification/s3-encryption/client.md#required-api-operations
321321
//= type=implication
322-
//# PutObject MUST be implemented by the S3EC.
322+
//# - PutObject MUST be implemented by the S3EC.
323323
/**
324324
* See {@link S3EncryptionClient#putObject(PutObjectRequest, RequestBody)}.
325325
* <p>
@@ -359,7 +359,7 @@ public PutObjectResponse putObject(PutObjectRequest putObjectRequest, RequestBod
359359
try {
360360
//= specification/s3-encryption/client.md#required-api-operations
361361
//= type=implication
362-
//# PutObject MUST encrypt its input data before it is uploaded to S3.
362+
//# - PutObject MUST encrypt its input data before it is uploaded to S3.
363363
CompletableFuture<PutObjectResponse> futurePut = pipeline.putObject(putObjectRequest,
364364
AsyncRequestBody.fromInputStream(
365365
requestBody.contentStreamProvider().newStream(),
@@ -386,7 +386,7 @@ public PutObjectResponse putObject(PutObjectRequest putObjectRequest, RequestBod
386386

387387
//= specification/s3-encryption/client.md#required-api-operations
388388
//= type=implication
389-
//# GetObject MUST be implemented by the S3EC.
389+
//# - GetObject MUST be implemented by the S3EC.
390390
/**
391391
* See {@link S3EncryptionClient#getObject(GetObjectRequest, ResponseTransformer)}
392392
* <p>
@@ -410,7 +410,7 @@ public <T> T getObject(GetObjectRequest getObjectRequest,
410410

411411
//= specification/s3-encryption/client.md#required-api-operations
412412
//= type=implication
413-
//# GetObject MUST decrypt data received from the S3 server and return it as plaintext.
413+
//# - GetObject MUST decrypt data received from the S3 server and return it as plaintext.
414414
GetEncryptedObjectPipeline pipeline = GetEncryptedObjectPipeline.builder()
415415
.s3AsyncClient(_wrappedAsyncClient)
416416
.cryptoMaterialsManager(_cryptoMaterialsManager)
@@ -520,7 +520,7 @@ private <T extends Throwable> T onAbort(UploadObjectObserver observer, T t) {
520520

521521
//= specification/s3-encryption/client.md#required-api-operations
522522
//= type=implication
523-
//# DeleteObject MUST be implemented by the S3EC.
523+
//# - DeleteObject MUST be implemented by the S3EC.
524524
/**
525525
* See {@link S3Client#deleteObject(DeleteObjectRequest)}.
526526
* <p>
@@ -540,11 +540,11 @@ public DeleteObjectResponse deleteObject(DeleteObjectRequest deleteObjectRequest
540540
try {
541541
//= specification/s3-encryption/client.md#required-api-operations
542542
//= type=implementation
543-
//# DeleteObject MUST delete the given object key.
543+
//# - DeleteObject MUST delete the given object key.
544544
DeleteObjectResponse deleteObjectResponse = _wrappedAsyncClient.deleteObject(actualRequest).join();
545545
//= specification/s3-encryption/client.md#required-api-operations
546546
//= type=implementation
547-
//# DeleteObject MUST delete the associated instruction file using the default instruction file suffix.
547+
//# - DeleteObject MUST delete the associated instruction file using the default instruction file suffix.
548548
String instructionObjectKey = deleteObjectRequest.key() + DEFAULT_INSTRUCTION_FILE_SUFFIX;
549549
_wrappedAsyncClient.deleteObject(builder -> builder
550550
.overrideConfiguration(API_NAME_INTERCEPTOR)
@@ -561,7 +561,7 @@ public DeleteObjectResponse deleteObject(DeleteObjectRequest deleteObjectRequest
561561

562562
//= specification/s3-encryption/client.md#required-api-operations
563563
//= type=implication
564-
//# DeleteObjects MUST be implemented by the S3EC.
564+
//# - DeleteObjects MUST be implemented by the S3EC.
565565
/**
566566
* See {@link S3Client#deleteObjects(DeleteObjectsRequest)}.
567567
* <p>
@@ -580,11 +580,11 @@ public DeleteObjectsResponse deleteObjects(DeleteObjectsRequest deleteObjectsReq
580580
try {
581581
//= specification/s3-encryption/client.md#required-api-operations
582582
//= type=implementation
583-
//# DeleteObjects MUST delete each of the given objects.
583+
//# - DeleteObjects MUST delete each of the given objects.
584584
DeleteObjectsResponse deleteObjectsResponse = _wrappedAsyncClient.deleteObjects(actualRequest).join();
585585
//= specification/s3-encryption/client.md#required-api-operations
586586
//= type=implementation
587-
//# DeleteObjects MUST delete each of the corresponding instruction files using the default instruction file suffix.
587+
//# - DeleteObjects MUST delete each of the corresponding instruction files using the default instruction file suffix.
588588
List<ObjectIdentifier> deleteObjects = instructionFileKeysToDelete(deleteObjectsRequest);
589589
_wrappedAsyncClient.deleteObjects(DeleteObjectsRequest.builder()
590590
.overrideConfiguration(API_NAME_INTERCEPTOR)
@@ -601,7 +601,7 @@ public DeleteObjectsResponse deleteObjects(DeleteObjectsRequest deleteObjectsReq
601601

602602
//= specification/s3-encryption/client.md#optional-api-operations
603603
//= type=implication
604-
//# CreateMultipartUpload MAY be implemented by the S3EC.
604+
//# - CreateMultipartUpload MAY be implemented by the S3EC.
605605
/**
606606
* See {@link S3Client#createMultipartUpload(CreateMultipartUploadRequest)}
607607
* <p>
@@ -625,7 +625,7 @@ public CreateMultipartUploadResponse createMultipartUpload(CreateMultipartUpload
625625

626626
//= specification/s3-encryption/client.md#optional-api-operations
627627
//= type=implication
628-
//# UploadPart MAY be implemented by the S3EC.
628+
//# - UploadPart MAY be implemented by the S3EC.
629629
/**
630630
* See {@link S3Client#uploadPart(UploadPartRequest, RequestBody)}
631631
*
@@ -651,7 +651,7 @@ public UploadPartResponse uploadPart(UploadPartRequest request, RequestBody requ
651651

652652
//= specification/s3-encryption/client.md#optional-api-operations
653653
//= type=implication
654-
//# CompleteMultipartUpload MAY be implemented by the S3EC.
654+
//# - CompleteMultipartUpload MAY be implemented by the S3EC.
655655
/**
656656
* See {@link S3Client#completeMultipartUpload(CompleteMultipartUploadRequest)}
657657
* @param request the request instance
@@ -671,7 +671,7 @@ public CompleteMultipartUploadResponse completeMultipartUpload(CompleteMultipart
671671

672672
//= specification/s3-encryption/client.md#optional-api-operations
673673
//= type=implication
674-
//# AbortMultipartUpload MAY be implemented by the S3EC.
674+
//# - AbortMultipartUpload MAY be implemented by the S3EC.
675675
/**
676676
* See {@link S3Client#abortMultipartUpload(AbortMultipartUploadRequest)}
677677
* @param request the request instance
@@ -765,7 +765,7 @@ private Builder() {
765765
@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Pass mutability into wrapping client")
766766
public Builder wrappedClient(S3Client _wrappedClient) {
767767
//= specification/s3-encryption/client.md#wrapped-s3-client-s
768-
//= type=exception
768+
//= type=implementation
769769
//# The S3EC MUST NOT support use of S3EC as the provided S3 client during its initialization; it MUST throw an exception in this case.
770770
if (_wrappedClient instanceof S3EncryptionClient) {
771771
throw new S3EncryptionClientException("Cannot use S3EncryptionClient as wrapped client");
@@ -787,7 +787,7 @@ public Builder wrappedClient(S3Client _wrappedClient) {
787787
@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Pass mutability into wrapping client")
788788
public Builder wrappedAsyncClient(S3AsyncClient _wrappedAsyncClient) {
789789
//= specification/s3-encryption/client.md#wrapped-s3-client-s
790-
//= type=exception
790+
//= type=implementation
791791
//# The S3EC MUST NOT support use of S3EC as the provided S3 client during its initialization; it MUST throw an exception in this case.
792792
if (_wrappedAsyncClient instanceof S3AsyncEncryptionClient) {
793793
throw new S3EncryptionClientException("Cannot use S3AsyncEncryptionClient as wrapped client");
@@ -887,7 +887,7 @@ private void checkKeyOptions() {
887887
}
888888

889889
//= specification/s3-encryption/client.md#cryptographic-materials
890-
//= type=exception
890+
//= type=implementation
891891
//# If both a CMM and a Keyring are provided, the S3EC MUST throw an exception.
892892
throw new S3EncryptionClientException("Only one may be set of: crypto materials manager, keyring, AES key, RSA key pair, KMS key id");
893893
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ private DecryptionMaterials prepareMaterialsFromRequest(final GetObjectRequest g
8080
//# When enabled, the S3EC MUST be able to decrypt objects encrypted with all content encryption algorithms (both legacy and fully supported).
8181
if (!_enableLegacyUnauthenticatedModes && algorithmSuite.isLegacy()) {
8282
//= specification/s3-encryption/client.md#enable-legacy-unauthenticated-modes
83-
//= type=exception
83+
//= type=implementation
8484
//# When disabled, the S3EC MUST NOT decrypt objects encrypted using legacy content encryption algorithms; it MUST throw an exception when attempting to decrypt an object encrypted with a legacy content encryption algorithm.
8585
throw new S3EncryptionClientException("Enable legacy unauthenticated modes to use legacy content decryption: " + algorithmSuite.cipherName());
8686
}

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public CreateMultipartUploadResponse createMultipartUpload(CreateMultipartUpload
7676

7777
//= specification/s3-encryption/client.md#optional-api-operations
7878
//= type=implication
79-
//# If implemented, CreateMultipartUpload MUST initiate a multipart upload.
79+
//# - If implemented, CreateMultipartUpload MUST initiate a multipart upload.
8080
CreateMultipartUploadResponse response = _s3AsyncClient.createMultipartUpload(request).join();
8181

8282
MultipartUploadMaterials mpuMaterials = MultipartUploadMaterials.builder()
@@ -138,19 +138,19 @@ public UploadPartResponse uploadPart(UploadPartRequest request, RequestBody requ
138138
final UploadPartResponse response;
139139
//= specification/s3-encryption/client.md#optional-api-operations
140140
//= type=implication
141-
//# Each part MUST be encrypted in sequence.
141+
//# - Each part MUST be encrypted in sequence.
142142
materials.beginPartUpload(actualRequest.partNumber(), partContentLength);
143143
//= specification/s3-encryption/client.md#optional-api-operations
144144
//= type=implication
145-
//# Each part MUST be encrypted using the same cipher instance for each part.
145+
//# - Each part MUST be encrypted using the same cipher instance for each part.
146146
Cipher cipher = materials.getCipher(materials.getIv());
147147

148148
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
149149

150150
try {
151151
//= specification/s3-encryption/client.md#optional-api-operations
152152
//= type=implication
153-
//# UploadPart MUST encrypt each part.
153+
//# - UploadPart MUST encrypt each part.
154154
final AsyncRequestBody cipherAsyncRequestBody = new CipherAsyncRequestBody(
155155
AsyncRequestBody.fromInputStream(
156156
requestBody.contentStreamProvider().newStream(),
@@ -170,8 +170,6 @@ public UploadPartResponse uploadPart(UploadPartRequest request, RequestBody requ
170170
}
171171
// Ensures parts are not retried to avoid corrupting ciphertext
172172
AsyncRequestBody noRetryBody = new NoRetriesAsyncRequestBody(cipherAsyncRequestBody);
173-
//= specification/s3-encryption/client.md#optional-api-operations
174-
//= type=implication
175173
response = _s3AsyncClient.uploadPart(actualRequest, noRetryBody).join();
176174
} finally {
177175
materials.endPartUpload();
@@ -202,7 +200,7 @@ public CompleteMultipartUploadResponse completeMultipartUpload(CompleteMultipart
202200

203201
//= specification/s3-encryption/client.md#optional-api-operations
204202
//= type=implication
205-
//# CompleteMultipartUpload MUST complete the multipart upload.
203+
//# - CompleteMultipartUpload MUST complete the multipart upload.
206204
CompleteMultipartUploadResponse response = _s3AsyncClient.completeMultipartUpload(actualRequest).join();
207205

208206
_multipartUploadMaterials.remove(uploadId);
@@ -216,7 +214,7 @@ public AbortMultipartUploadResponse abortMultipartUpload(AbortMultipartUploadReq
216214
.build();
217215
//= specification/s3-encryption/client.md#optional-api-operations
218216
//= type=implication
219-
//# AbortMultipartUpload MUST abort the multipart upload.
217+
//# - AbortMultipartUpload MUST abort the multipart upload.
220218
return _s3AsyncClient.abortMultipartUpload(actualRequest).join();
221219
}
222220

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,38 @@
44

55
import java.util.List;
66

7+
//= specification/s3-encryption/materials/keyrings.md#interface
8+
//= type=implication
9+
//# The Keyring interface and its operations SHOULD adhere to the naming conventions of the implementation language.
710
/**
811
* Keyring defines the interface for wrapping data keys. A {@link CryptographicMaterialsManager} will use
912
* keyrings to encrypt and decrypt data keys.
1013
*/
1114
public interface Keyring {
15+
//= specification/s3-encryption/materials/keyrings.md#interface
16+
//= type=implication
17+
//# The Keyring interface and its operations SHOULD adhere to the naming conventions of the implementation language.
18+
//= specification/s3-encryption/materials/keyrings.md#interface
19+
//= type=implication
20+
//# The Keyring interface MUST include the OnEncrypt operation.
21+
//= specification/s3-encryption/materials/keyrings.md#interface
22+
//= type=implication
23+
//# The OnEncrypt operation MUST accept an instance of EncryptionMaterials as input.
24+
//= specification/s3-encryption/materials/keyrings.md#interface
25+
//= type=implication
26+
//# The OnEncrypt operation MUST return an instance of EncryptionMaterials as output.
1227
EncryptionMaterials onEncrypt(final EncryptionMaterials materials);
28+
//= specification/s3-encryption/materials/keyrings.md#interface
29+
//= type=implication
30+
//# The Keyring interface and its operations SHOULD adhere to the naming conventions of the implementation language.
31+
//= specification/s3-encryption/materials/keyrings.md#interface
32+
//= type=implication
33+
//# The Keyring interface MUST include the OnDecrypt operation.
34+
//= specification/s3-encryption/materials/keyrings.md#interface
35+
//= type=implication
36+
//# The OnDecrypt operation MUST accept an instance of DecryptionMaterials and a collection of EncryptedDataKey instances as input.
37+
//= specification/s3-encryption/materials/keyrings.md#interface
38+
//= type=implication
39+
//# The OnDecrypt operation MUST return an instance of DecryptionMaterials as output.
1340
DecryptionMaterials onDecrypt(final DecryptionMaterials materials, final List<EncryptedDataKey> encryptedDataKeys);
1441
}

0 commit comments

Comments
 (0)