Skip to content

Commit 8b9f9ee

Browse files
committed
chore(spec): add spec and Duvet annotations for KmsKeyring
1 parent a39f752 commit 8b9f9ee

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
@@ -212,7 +212,7 @@ public static Consumer<AwsRequestOverrideConfiguration.Builder> withAdditionalCo
212212

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

@@ -317,7 +317,7 @@ private void enforceRotation(EncryptionMaterials newEncryptionMaterials, GetObje
317317

318318
//= specification/s3-encryption/client.md#required-api-operations
319319
//= type=implication
320-
//# PutObject MUST be implemented by the S3EC.
320+
//# - PutObject MUST be implemented by the S3EC.
321321
/**
322322
* See {@link S3EncryptionClient#putObject(PutObjectRequest, RequestBody)}.
323323
* <p>
@@ -357,7 +357,7 @@ public PutObjectResponse putObject(PutObjectRequest putObjectRequest, RequestBod
357357
try {
358358
//= specification/s3-encryption/client.md#required-api-operations
359359
//= type=implication
360-
//# PutObject MUST encrypt its input data before it is uploaded to S3.
360+
//# - PutObject MUST encrypt its input data before it is uploaded to S3.
361361
CompletableFuture<PutObjectResponse> futurePut = pipeline.putObject(putObjectRequest,
362362
AsyncRequestBody.fromInputStream(
363363
requestBody.contentStreamProvider().newStream(),
@@ -384,7 +384,7 @@ public PutObjectResponse putObject(PutObjectRequest putObjectRequest, RequestBod
384384

385385
//= specification/s3-encryption/client.md#required-api-operations
386386
//= type=implication
387-
//# GetObject MUST be implemented by the S3EC.
387+
//# - GetObject MUST be implemented by the S3EC.
388388
/**
389389
* See {@link S3EncryptionClient#getObject(GetObjectRequest, ResponseTransformer)}
390390
* <p>
@@ -408,7 +408,7 @@ public <T> T getObject(GetObjectRequest getObjectRequest,
408408

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

519519
//= specification/s3-encryption/client.md#required-api-operations
520520
//= type=implication
521-
//# DeleteObject MUST be implemented by the S3EC.
521+
//# - DeleteObject MUST be implemented by the S3EC.
522522
/**
523523
* See {@link S3Client#deleteObject(DeleteObjectRequest)}.
524524
* <p>
@@ -538,11 +538,11 @@ public DeleteObjectResponse deleteObject(DeleteObjectRequest deleteObjectRequest
538538
try {
539539
//= specification/s3-encryption/client.md#required-api-operations
540540
//= type=implementation
541-
//# DeleteObject MUST delete the given object key.
541+
//# - DeleteObject MUST delete the given object key.
542542
DeleteObjectResponse deleteObjectResponse = _wrappedAsyncClient.deleteObject(actualRequest).join();
543543
//= specification/s3-encryption/client.md#required-api-operations
544544
//= type=implementation
545-
//# DeleteObject MUST delete the associated instruction file using the default instruction file suffix.
545+
//# - DeleteObject MUST delete the associated instruction file using the default instruction file suffix.
546546
String instructionObjectKey = deleteObjectRequest.key() + DEFAULT_INSTRUCTION_FILE_SUFFIX;
547547
_wrappedAsyncClient.deleteObject(builder -> builder
548548
.overrideConfiguration(API_NAME_INTERCEPTOR)
@@ -559,7 +559,7 @@ public DeleteObjectResponse deleteObject(DeleteObjectRequest deleteObjectRequest
559559

560560
//= specification/s3-encryption/client.md#required-api-operations
561561
//= type=implication
562-
//# DeleteObjects MUST be implemented by the S3EC.
562+
//# - DeleteObjects MUST be implemented by the S3EC.
563563
/**
564564
* See {@link S3Client#deleteObjects(DeleteObjectsRequest)}.
565565
* <p>
@@ -578,11 +578,11 @@ public DeleteObjectsResponse deleteObjects(DeleteObjectsRequest deleteObjectsReq
578578
try {
579579
//= specification/s3-encryption/client.md#required-api-operations
580580
//= type=implementation
581-
//# DeleteObjects MUST delete each of the given objects.
581+
//# - DeleteObjects MUST delete each of the given objects.
582582
DeleteObjectsResponse deleteObjectsResponse = _wrappedAsyncClient.deleteObjects(actualRequest).join();
583583
//= specification/s3-encryption/client.md#required-api-operations
584584
//= type=implementation
585-
//# DeleteObjects MUST delete each of the corresponding instruction files using the default instruction file suffix.
585+
//# - DeleteObjects MUST delete each of the corresponding instruction files using the default instruction file suffix.
586586
List<ObjectIdentifier> deleteObjects = instructionFileKeysToDelete(deleteObjectsRequest);
587587
_wrappedAsyncClient.deleteObjects(DeleteObjectsRequest.builder()
588588
.overrideConfiguration(API_NAME_INTERCEPTOR)
@@ -599,7 +599,7 @@ public DeleteObjectsResponse deleteObjects(DeleteObjectsRequest deleteObjectsReq
599599

600600
//= specification/s3-encryption/client.md#optional-api-operations
601601
//= type=implication
602-
//# CreateMultipartUpload MAY be implemented by the S3EC.
602+
//# - CreateMultipartUpload MAY be implemented by the S3EC.
603603
/**
604604
* See {@link S3Client#createMultipartUpload(CreateMultipartUploadRequest)}
605605
* <p>
@@ -623,7 +623,7 @@ public CreateMultipartUploadResponse createMultipartUpload(CreateMultipartUpload
623623

624624
//= specification/s3-encryption/client.md#optional-api-operations
625625
//= type=implication
626-
//# UploadPart MAY be implemented by the S3EC.
626+
//# - UploadPart MAY be implemented by the S3EC.
627627
/**
628628
* See {@link S3Client#uploadPart(UploadPartRequest, RequestBody)}
629629
*
@@ -649,7 +649,7 @@ public UploadPartResponse uploadPart(UploadPartRequest request, RequestBody requ
649649

650650
//= specification/s3-encryption/client.md#optional-api-operations
651651
//= type=implication
652-
//# CompleteMultipartUpload MAY be implemented by the S3EC.
652+
//# - CompleteMultipartUpload MAY be implemented by the S3EC.
653653
/**
654654
* See {@link S3Client#completeMultipartUpload(CompleteMultipartUploadRequest)}
655655
* @param request the request instance
@@ -669,7 +669,7 @@ public CompleteMultipartUploadResponse completeMultipartUpload(CompleteMultipart
669669

670670
//= specification/s3-encryption/client.md#optional-api-operations
671671
//= type=implication
672-
//# AbortMultipartUpload MAY be implemented by the S3EC.
672+
//# - AbortMultipartUpload MAY be implemented by the S3EC.
673673
/**
674674
* See {@link S3Client#abortMultipartUpload(AbortMultipartUploadRequest)}
675675
* @param request the request instance
@@ -763,7 +763,7 @@ private Builder() {
763763
@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Pass mutability into wrapping client")
764764
public Builder wrappedClient(S3Client _wrappedClient) {
765765
//= specification/s3-encryption/client.md#wrapped-s3-client-s
766-
//= type=exception
766+
//= type=implementation
767767
//# The S3EC MUST NOT support use of S3EC as the provided S3 client during its initialization; it MUST throw an exception in this case.
768768
if (_wrappedClient instanceof S3EncryptionClient) {
769769
throw new S3EncryptionClientException("Cannot use S3EncryptionClient as wrapped client");
@@ -785,7 +785,7 @@ public Builder wrappedClient(S3Client _wrappedClient) {
785785
@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Pass mutability into wrapping client")
786786
public Builder wrappedAsyncClient(S3AsyncClient _wrappedAsyncClient) {
787787
//= specification/s3-encryption/client.md#wrapped-s3-client-s
788-
//= type=exception
788+
//= type=implementation
789789
//# The S3EC MUST NOT support use of S3EC as the provided S3 client during its initialization; it MUST throw an exception in this case.
790790
if (_wrappedAsyncClient instanceof S3AsyncEncryptionClient) {
791791
throw new S3EncryptionClientException("Cannot use S3AsyncEncryptionClient as wrapped client");
@@ -885,7 +885,7 @@ private void checkKeyOptions() {
885885
}
886886

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

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)