Skip to content

Commit 2301f3c

Browse files
committed
use implication/implementation/test annotation types instead of just comments for everything
1 parent 2cdb8b3 commit 2301f3c

File tree

7 files changed

+116
-6
lines changed

7 files changed

+116
-6
lines changed

specification

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

Lines changed: 49 additions & 1 deletion
Large diffs are not rendered by default.

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,12 @@ private DecryptionMaterials prepareMaterialsFromRequest(final GetObjectRequest g
7676

7777
AlgorithmSuite algorithmSuite = contentMetadata.algorithmSuite();
7878
//= specification/s3-encryption/client.md#enable-legacy-unauthenticated-modes
79+
//= type=implication
7980
//# When enabled, the S3EC MUST be able to decrypt objects encrypted with all content encryption algorithms (both legacy and fully supported).
8081
if (!_enableLegacyUnauthenticatedModes && algorithmSuite.isLegacy()) {
8182
//= specification/s3-encryption/client.md#enable-legacy-unauthenticated-modes
82-
//# When disabled, the S3EC MUST NOT decrypt objects encrypted using legacy content encryption algorithms.
83+
//= type=exception
84+
//# 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.
8385
throw new S3EncryptionClientException("Enable legacy unauthenticated modes to use legacy content decryption: " + algorithmSuite.cipherName());
8486
}
8587

@@ -151,13 +153,15 @@ public void onStream(SdkPublisher<ByteBuffer> ciphertextPublisher) {
151153
|| algorithmSuite.equals(AlgorithmSuite.ALG_AES_256_CTR_IV16_TAG16_NO_KDF)
152154
|| _enableDelayedAuthentication) {
153155
//= specification/s3-encryption/client.md#enable-delayed-authentication
156+
//= type=implication
154157
//# When enabled, the S3EC MAY release plaintext from a stream which has not been authenticated.
155158
// CBC and GCM with delayed auth enabled use a standard publisher
156159
CipherPublisher plaintextPublisher = new CipherPublisher(ciphertextPublisher,
157160
getObjectResponse.contentLength(), desiredRange, contentMetadata.contentRange(), algorithmSuite.cipherTagLengthBits(), materials, iv);
158161
wrappedAsyncResponseTransformer.onStream(plaintextPublisher);
159162
} else {
160163
//= specification/s3-encryption/client.md#enable-delayed-authentication
164+
//= type=implication
161165
//# When disabled the S3EC MUST NOT release plaintext from a stream which has not been authenticated.
162166
// Use buffered publisher for GCM when delayed auth is not enabled
163167
BufferedCipherPublisher plaintextPublisher = new BufferedCipherPublisher(ciphertextPublisher,

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public CreateMultipartUploadResponse createMultipartUpload(CreateMultipartUpload
7575
.build();
7676

7777
//= specification/s3-encryption/client.md#api-operations
78+
//= type=implication
7879
//# If implemented, CreateMultipartUpload MUST initiate a multipart upload.
7980
CreateMultipartUploadResponse response = _s3AsyncClient.createMultipartUpload(request).join();
8081

@@ -136,16 +137,19 @@ public UploadPartResponse uploadPart(UploadPartRequest request, RequestBody requ
136137
}
137138
final UploadPartResponse response;
138139
//= specification/s3-encryption/client.md#api-operations
140+
//= type=implication
139141
//# Each part MUST be encrypted in sequence.
140142
materials.beginPartUpload(actualRequest.partNumber(), partContentLength);
141143
//= specification/s3-encryption/client.md#api-operations
144+
//= type=implication
142145
//# Each part MUST be encrypted using the same cipher instance for each part.
143146
Cipher cipher = materials.getCipher(materials.getIv());
144147

145148
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
146149

147150
try {
148151
//= specification/s3-encryption/client.md#api-operations
152+
//= type=implication
149153
//# UploadPart MUST encrypt each part.
150154
final AsyncRequestBody cipherAsyncRequestBody = new CipherAsyncRequestBody(
151155
AsyncRequestBody.fromInputStream(
@@ -167,6 +171,7 @@ public UploadPartResponse uploadPart(UploadPartRequest request, RequestBody requ
167171
// Ensures parts are not retried to avoid corrupting ciphertext
168172
AsyncRequestBody noRetryBody = new NoRetriesAsyncRequestBody(cipherAsyncRequestBody);
169173
//= specification/s3-encryption/client.md#api-operations
174+
//= type=implication
170175
response = _s3AsyncClient.uploadPart(actualRequest, noRetryBody).join();
171176
} finally {
172177
materials.endPartUpload();
@@ -196,6 +201,7 @@ public CompleteMultipartUploadResponse completeMultipartUpload(CompleteMultipart
196201
.build();
197202

198203
//= specification/s3-encryption/client.md#api-operations
204+
//= type=implication
199205
//# CompleteMultipartUpload MUST complete the multipart upload.
200206
CompleteMultipartUploadResponse response = _s3AsyncClient.completeMultipartUpload(actualRequest).join();
201207

@@ -209,6 +215,7 @@ public AbortMultipartUploadResponse abortMultipartUpload(AbortMultipartUploadReq
209215
.overrideConfiguration(API_NAME_INTERCEPTOR)
210216
.build();
211217
//= specification/s3-encryption/client.md#api-operations
218+
//= type=implication
212219
//# AbortMultipartUpload MUST abort the multipart upload.
213220
return _s3AsyncClient.abortMultipartUpload(actualRequest).join();
214221
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,12 @@ public DecryptionMaterials onDecrypt(final DecryptionMaterials materials, List<E
116116
}
117117

118118
//= specification/s3-encryption/client.md#enable-legacy-wrapping-algorithms
119+
//= type=implication
119120
//# When enabled, the S3EC MUST be able to decrypt objects encrypted with all supported wrapping algorithms (both legacy and fully supported).
120121
if (decryptStrategy.isLegacy() && !_enableLegacyWrappingAlgorithms) {
121122
//= specification/s3-encryption/client.md#enable-legacy-wrapping-algorithms
122-
//# When disabled, the S3EC MUST NOT decrypt objects encrypted using legacy wrapping algorithms.
123+
//= type=exception
124+
//# When disabled, the S3EC MUST NOT decrypt objects encrypted using legacy wrapping algorithms; it MUST throw an exception when attempting to decrypt an object encrypted with a legacy wrapping algorithm.
123125
throw new S3EncryptionClientException("Enable legacy wrapping algorithms to use legacy key wrapping algorithm: " + keyProviderInfo);
124126
}
125127

src/test/java/software/amazon/encryption/s3/S3EncryptionClientCompatibilityTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,9 @@ public void AesCbcV1toV3FailsWhenUnauthencticateModeDisabled() {
836836
final String input = "AesCbcV1toV3";
837837
v1Client.putObject(BUCKET, objectKey, input);
838838

839+
//= specification/s3-encryption/client.md#enable-legacy-wrapping-algorithms
840+
//= type=test
841+
//# When disabled, the S3EC MUST NOT decrypt objects encrypted using legacy wrapping algorithms; it MUST throw an exception when attempting to decrypt an object encrypted with a legacy wrapping algorithm.
839842
assertThrows(S3EncryptionClientException.class, () -> v3Client.getObjectAsBytes(builder -> builder
840843
.bucket(BUCKET)
841844
.key(objectKey)));
@@ -870,6 +873,9 @@ public void AesCbcV1toV3FailsWhenLegacyKeyringDisabled() {
870873
final String input = "AesCbcV1toV3";
871874
v1Client.putObject(BUCKET, objectKey, input);
872875

876+
//= specification/s3-encryption/client.md#enable-legacy-wrapping-algorithms
877+
//= type=test
878+
//# When disabled, the S3EC MUST NOT decrypt objects encrypted using legacy wrapping algorithms; it MUST throw an exception when attempting to decrypt an object encrypted with a legacy wrapping algorithm.
873879
assertThrows(S3EncryptionClientException.class, () -> v3Client.getObjectAsBytes(builder -> builder
874880
.bucket(BUCKET)
875881
.key(objectKey)));

src/test/java/software/amazon/encryption/s3/S3EncryptionClientTest.java

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import software.amazon.encryption.s3.materials.CryptographicMaterialsManager;
4242
import software.amazon.encryption.s3.materials.DefaultCryptoMaterialsManager;
4343
import software.amazon.encryption.s3.materials.KmsKeyring;
44+
import software.amazon.encryption.s3.materials.PartialRsaKeyPair;
45+
import software.amazon.encryption.s3.materials.RsaKeyring;
4446
import software.amazon.encryption.s3.utils.BoundedInputStream;
4547
import software.amazon.encryption.s3.utils.S3EncryptionClientTestResources;
4648

@@ -98,6 +100,9 @@ public static void setUp() throws NoSuchAlgorithmException {
98100
RSA_KEY_PAIR = keyPairGen.generateKeyPair();
99101
}
100102

103+
//= specification/s3-encryption/client.md#aws-sdk-compatibility
104+
//= type=test
105+
//# The S3EC SHOULD support invoking operations unrelated to client-side encryption e.g. CopyObject as the conventional AWS SDK S3 client would.
101106
@Test
102107
public void copyObjectTransparently() {
103108
final String objectKey = appendTestSuffix("copy-object-from-here");
@@ -161,10 +166,15 @@ public void deleteObjectWithInstructionFileSuccess() {
161166
v3Client.deleteObject(builder -> builder.bucket(BUCKET).key(objectKey));
162167

163168
S3Client s3Client = S3Client.builder().build();
164-
// Assert throw NoSuchKeyException when getObject for objectKey
169+
//= specification/s3-encryption/client.md#api-operations
170+
//= type=test
171+
//# DeleteObject MUST delete the given object key.
165172
assertThrows(S3Exception.class, () -> s3Client.getObject(builder -> builder
166173
.bucket(BUCKET)
167174
.key(objectKey)));
175+
//= specification/s3-encryption/client.md#api-operations
176+
//= type=test
177+
//# DeleteObject MUST delete the associated instruction file using the default instruction file suffix.
168178
assertThrows(S3Exception.class, () -> s3Client.getObject(builder -> builder
169179
.bucket(BUCKET)
170180
.key(objectKey + ".instruction")));
@@ -208,10 +218,15 @@ public void deleteObjectsWithInstructionFilesSuccess() {
208218
.delete(builder1 -> builder1.objects(objects)));
209219

210220
S3Client s3Client = S3Client.builder().build();
211-
// Assert throw NoSuchKeyException when getObject for any of objectKeys
221+
//= specification/s3-encryption/client.md#api-operations
222+
//= type=test
223+
//# DeleteObjects MUST delete each of the given objects.
212224
assertThrows(S3Exception.class, () -> s3Client.getObject(builder -> builder
213225
.bucket(BUCKET)
214226
.key(objectKeys[0])));
227+
//= specification/s3-encryption/client.md#api-operations
228+
//= type=test
229+
//# DeleteObjects MUST delete each of the corresponding instruction files using the default instruction file suffix.
215230
assertThrows(S3Exception.class, () -> s3Client.getObject(builder -> builder
216231
.bucket(BUCKET)
217232
.key(objectKeys[0] + ".instruction")));
@@ -292,6 +307,9 @@ public void getNonExistentObject() {
292307
v3Client.close();
293308
}
294309

310+
//= specification/s3-encryption/client.md#cryptographic-materials
311+
//= type=test
312+
//# The S3EC MUST accept either one CMM or one Keyring instance upon initialization.
295313
@Test
296314
public void s3EncryptionClientWithMultipleKeyringsFails() {
297315
assertThrows(S3EncryptionClientException.class, () -> S3EncryptionClient.builder()
@@ -300,6 +318,22 @@ public void s3EncryptionClientWithMultipleKeyringsFails() {
300318
.build());
301319
}
302320

321+
//= specification/s3-encryption/client.md#cryptographic-materials
322+
//= type=test
323+
//# If both a CMM and a Keyring are provided, the S3EC MUST throw an exception.
324+
@Test
325+
public void s3EncryptionClientWithCMMAndKeyringFails() {
326+
CryptographicMaterialsManager defaultCMM = DefaultCryptoMaterialsManager.builder()
327+
.keyring(RsaKeyring.builder()
328+
.wrappingKeyPair(new PartialRsaKeyPair(RSA_KEY_PAIR))
329+
.build())
330+
.build();
331+
assertThrows(S3EncryptionClientException.class, () -> S3EncryptionClient.builder()
332+
.aesKey(AES_KEY)
333+
.cryptoMaterialsManager(defaultCMM)
334+
.build());
335+
}
336+
303337
@Test
304338
public void s3EncryptionClientWithNoKeyringsFails() {
305339
assertThrows(S3EncryptionClientException.class, () -> S3EncryptionClient.builder()
@@ -440,6 +474,9 @@ public void s3EncryptionClientWithCmmFromKmsKeyIdSucceeds() {
440474
v3Client.close();
441475
}
442476

477+
//= specification/s3-encryption/client.md#wrapped-s3-client-s
478+
//= type=test
479+
//# The S3EC MUST support the option to provide an SDK S3 client instance during its initialization.
443480
@Test
444481
public void s3EncryptionClientWithWrappedS3ClientSucceeds() {
445482
final String objectKey = appendTestSuffix("wrapped-s3-client-with-kms-key-id");
@@ -462,6 +499,9 @@ public void s3EncryptionClientWithWrappedS3ClientSucceeds() {
462499
wrappingClient.close();
463500
}
464501

502+
//= specification/s3-encryption/client.md#wrapped-s3-client-s
503+
//= type=test
504+
//# The S3EC MUST NOT support use of S3EC as the provided S3 client during its initialization; it MUST throw an exception in this case.
465505
/**
466506
* S3EncryptionClient implements S3Client, so it can be passed into the builder as a wrappedClient.
467507
* However, is not a supported use case, and the builder should throw an exception if this happens.
@@ -854,6 +894,9 @@ public void s3EncryptionClientTopLevelCredentialsNullCreds() {
854894
}
855895
}
856896

897+
//= specification/s3-encryption/client.md#inherited-sdk-configuration
898+
//= type=test
899+
//# If the S3EC accepts SDK client configuration, the configuration MUST be applied to all wrapped SDK clients including the KMS client.
857900
@Test
858901
public void s3EncryptionClientTopLevelAlternateCredentials() {
859902
final String objectKey = appendTestSuffix("wrapped-s3-client-with-top-level-credentials");

0 commit comments

Comments
 (0)