From cd4188e838f52a4787e5e50f103af0e462bad9bf Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Thu, 30 Oct 2025 10:51:21 -0700 Subject: [PATCH 01/17] chore: add instruction file support to TestServer --- test-server/model/client.smithy | 7 +++++++ test-server/model/object.smithy | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/test-server/model/client.smithy b/test-server/model/client.smithy index 5514672f..842f2489 100644 --- a/test-server/model/client.smithy +++ b/test-server/model/client.smithy @@ -40,6 +40,12 @@ enum EncryptionAlgorithm { ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY } +structure InstructionFileConfig { + clientId: String, + enableInstructionFilePutObject: Boolean = false, + disableInstructionFile: Boolean = false +} + structure S3ECConfig { enableLegacyUnauthenticatedModes: Boolean = false, enableDelayedAuthenticationMode: Boolean = false, @@ -48,4 +54,5 @@ structure S3ECConfig { keyMaterial: KeyMaterial, commitmentPolicy: CommitmentPolicy, encryptionAlgorithm: EncryptionAlgorithm, + instructionFileConfig: InstructionFileConfig, } diff --git a/test-server/model/object.smithy b/test-server/model/object.smithy index a4b12d5a..6d793353 100644 --- a/test-server/model/object.smithy +++ b/test-server/model/object.smithy @@ -113,6 +113,11 @@ operation ReEncrypt { @required @notProperty clientID: String + + /// Custom instruction file suffix + @httpHeader("InstructionFileSuffix") + @notProperty + instructionFileSuffix: String } output := for Object { From faf77d4316f12e3ecd2106708f18353a69f71414 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Thu, 30 Oct 2025 11:25:30 -0700 Subject: [PATCH 02/17] fix makefile to wait --- test-server/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-server/Makefile b/test-server/Makefile index a166030a..be8df10b 100644 --- a/test-server/Makefile +++ b/test-server/Makefile @@ -3,10 +3,10 @@ .PHONY: all start-servers run-tests stop-servers clean ci check-env help # Default target -all: start-all-servers run-tests +all: start-all-servers wait-all-servers run-tests # CI target for GitHub Actions -ci: start-all-servers run-tests stop-servers +ci: start-all-servers wait-all-servers run-tests stop-servers SERVER_DIRS := $(shell find . -maxdepth 1 -type d -name '*-server' | sed 's|^\./||' | $(if $(FILTER),grep -E "$$(echo '$(FILTER)' | sed 's/,/|/g')",cat) | sort) From c38977e9658d84336a74f4151f0e008f58c0657e Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Thu, 30 Oct 2025 14:01:30 -0700 Subject: [PATCH 03/17] add a simple inst file test --- .../amazon/encryption/s3/RoundTripTests.java | 44 +++++++++++++++++++ test-server/model/client.smithy | 5 +++ 2 files changed, 49 insertions(+) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index e8dc4bae..cf9327be 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -17,7 +17,12 @@ import java.util.Map; import java.util.stream.Stream; +import com.amazonaws.services.s3.AmazonS3EncryptionClientV2; +import com.amazonaws.services.s3.AmazonS3EncryptionV2; +import com.amazonaws.services.s3.model.CryptoConfigurationV2; +import com.amazonaws.services.s3.model.EncryptionMaterials; import com.amazonaws.services.s3.model.KMSEncryptionMaterials; +import com.amazonaws.services.s3.model.StaticEncryptionMaterialsProvider; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -28,6 +33,7 @@ import software.amazon.encryption.s3.model.CreateClientOutput; import software.amazon.encryption.s3.model.GetObjectInput; import software.amazon.encryption.s3.model.GetObjectOutput; +import software.amazon.encryption.s3.model.InstructionFileConfig; import software.amazon.encryption.s3.model.KeyMaterial; import software.amazon.encryption.s3.model.PutObjectInput; import software.amazon.encryption.s3.model.S3ECConfig; @@ -416,4 +422,42 @@ public void kmsV1LegacyFailsWhenLegacyDisabled(TestUtils.LanguageServerTarget la } } } + + @ParameterizedTest(name = "{displayName} for Encrypt: Java, Decrypt: {0}") + @MethodSource("software.amazon.encryption.s3.TestUtils#clientsForTest") + public void instructionFileReadV2Format(TestUtils.LanguageServerTarget language) { + S3ECTestServerClient client = testServerClientFor(language); + final String objectKey = appendTestSuffix("read-instruction-file-v2-" + language); + final String input = "simple-test-input"; + KeyMaterial kmsKeyArn = KeyMaterial.builder() + .kmsKeyId(KMS_KEY_ARN) + .build(); + CreateClientOutput output1 = client.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .enableLegacyWrappingAlgorithms(true) + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .build()) + .build()); + String s3ECId = output1.getClientId(); + + // Write with instruction file using V2 client + EncryptionMaterialsProvider materialsProvider = new KMSEncryptionMaterialsProvider(KMS_KEY_ARN); + CryptoConfigurationV2 cryptoConfigurationV2 = new CryptoConfigurationV2(); + cryptoConfigurationV2.setStorageMode(CryptoStorageMode.InstructionFile); + AmazonS3EncryptionV2 v2Client = AmazonS3EncryptionClientV2.encryptionBuilder() + .withEncryptionMaterialsProvider(materialsProvider) + .withCryptoConfiguration(cryptoConfigurationV2) + .build(); + v2Client.putObject(BUCKET, objectKey, input); + + GetObjectOutput output = client.getObject(GetObjectInput.builder() + .clientID(s3ECId) + .bucket(BUCKET) + .key(objectKey) + .build()); + + assertEquals(input, new String(output.getBody().array())); + + } } diff --git a/test-server/model/client.smithy b/test-server/model/client.smithy index 842f2489..bba19b62 100644 --- a/test-server/model/client.smithy +++ b/test-server/model/client.smithy @@ -41,6 +41,11 @@ enum EncryptionAlgorithm { } structure InstructionFileConfig { + /// This allows specifying a (non-encrypted) client for languages which + /// support this for instruction files. + /// In general, languages should not require specifying it, + /// so it is best to leave it null until there's a good reason not to. + /// This also requires a way to create non-encrypted clients which we don't have yet. clientId: String, enableInstructionFilePutObject: Boolean = false, disableInstructionFile: Boolean = false From 9c37c0760abda2b1e698f13f1c2a4fed43b1bc6e Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Thu, 30 Oct 2025 14:35:34 -0700 Subject: [PATCH 04/17] skip .NET KMS inst files --- test-server/java-tests/build.gradle.kts | 1 + .../amazon/encryption/s3/RoundTripTests.java | 75 +++++++++++++++++++ .../amazon/encryption/s3/TestUtils.java | 5 ++ 3 files changed, 81 insertions(+) diff --git a/test-server/java-tests/build.gradle.kts b/test-server/java-tests/build.gradle.kts index bc37514f..106f82ef 100644 --- a/test-server/java-tests/build.gradle.kts +++ b/test-server/java-tests/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter:5.13.0") testRuntimeOnly("org.junit.platform:junit-platform-launcher") testImplementation("com.amazonaws:aws-java-sdk:1.12.788") + testImplementation("software.amazon.awssdk:s3:2.37.1") testImplementation("org.bouncycastle:bcprov-jdk15on:1.70") } diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index cf9327be..0d5e2830 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -6,6 +6,7 @@ package software.amazon.encryption.s3; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static software.amazon.encryption.s3.TestUtils.*; @@ -27,6 +28,9 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.encryption.s3.client.S3ECTestServerClient; import software.amazon.encryption.s3.model.CommitmentPolicy; import software.amazon.encryption.s3.model.CreateClientInput; @@ -426,6 +430,9 @@ public void kmsV1LegacyFailsWhenLegacyDisabled(TestUtils.LanguageServerTarget la @ParameterizedTest(name = "{displayName} for Encrypt: Java, Decrypt: {0}") @MethodSource("software.amazon.encryption.s3.TestUtils#clientsForTest") public void instructionFileReadV2Format(TestUtils.LanguageServerTarget language) { + if (KMS_INSTRUCTION_FILE_UNSUPPORTED.contains(language.getLanguageName())) { + return; + } S3ECTestServerClient client = testServerClientFor(language); final String objectKey = appendTestSuffix("read-instruction-file-v2-" + language); final String input = "simple-test-input"; @@ -451,6 +458,7 @@ public void instructionFileReadV2Format(TestUtils.LanguageServerTarget language) .build(); v2Client.putObject(BUCKET, objectKey, input); + // Read should be enabled by default GetObjectOutput output = client.getObject(GetObjectInput.builder() .clientID(s3ECId) .bucket(BUCKET) @@ -458,6 +466,73 @@ public void instructionFileReadV2Format(TestUtils.LanguageServerTarget language) .build()); assertEquals(input, new String(output.getBody().array())); + } + @ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}") + @MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients") + public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageServerTarget decLang) { + // Skip for now + if (true) { + return; + } + if (KMS_INSTRUCTION_FILE_UNSUPPORTED.contains(encLang.getLanguageName())) { + return; + } + if (KMS_INSTRUCTION_FILE_UNSUPPORTED.contains(decLang.getLanguageName())) { + return; + } + S3ECTestServerClient encClient = testServerClientFor(encLang); + S3ECTestServerClient decClient = testServerClientFor(decLang); + final String objectKey = appendTestSuffix(String.format("write-%s-read-%s-instruction-file", encLang.getLanguageName(), decLang.getLanguageName())); + final String input = "simple-test-input"; + KeyMaterial kmsKeyArn = KeyMaterial.builder() + .kmsKeyId(KMS_KEY_ARN) + .build(); + CreateClientOutput encOutput = encClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .instructionFileConfig(InstructionFileConfig.builder() + .enableInstructionFilePutObject(true) + .build()) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .build()) + .build()); + String encS3ECId = encOutput.getClientId(); + CreateClientOutput decOutput = decClient.createClient(CreateClientInput.builder() + .config(S3ECConfig.builder() + .keyMaterial(kmsKeyArn) + .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .build()) + .build()); + String decS3ECId = decOutput.getClientId(); + + // Write with instruction file + encClient.putObject(PutObjectInput.builder() + .clientID(encS3ECId) + .bucket(BUCKET) + .key(objectKey) + .body(ByteBuffer.wrap(input.getBytes(StandardCharsets.UTF_8))) + .build()); + + // Assert using Java plaintext client that an instruction file exists + ResponseBytes ptInstFile; + try (S3Client ptS3Client = S3Client.create()) { + ptInstFile = ptS3Client.getObjectAsBytes(builder -> builder + .bucket(BUCKET) + .key(objectKey + ".instruction") + .build()); + } + // Check for inst file key + assertTrue(ptInstFile.response().metadata().containsKey("x-amz-crypto-instr-file")); + assertFalse(ptInstFile.asUtf8String().isEmpty()); + + // Read should be enabled by default + GetObjectOutput output = decClient.getObject(GetObjectInput.builder() + .clientID(decS3ECId) + .bucket(BUCKET) + .key(objectKey) + .build()); + + assertEquals(input, new String(output.getBody().array())); } } diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java index 4b0c8e74..0ed87fa3 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java @@ -97,6 +97,11 @@ public class TestUtils { public static final Set ENCRYPTION_CONTEXT_ON_ENCRYPT_UNSUPPORTED = Set.of(NET_V2_CURRENT, NET_V3); + // .NET only supports decrypting instruction files using AES and RSA. + // Python MUST support decrypting KMS instruction files, but does not yet. + public static final Set KMS_INSTRUCTION_FILE_UNSUPPORTED = + Set.of(NET_V2_CURRENT, NET_V2_TRANSITION, NET_V3, PYTHON_V3); + public static final Set CURRENT_VERSIONS = Set.of( JAVA_V3_CURRENT, From cd5ddcb36a0a3a18ce2eae624627fc14a5d852e2 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Thu, 30 Oct 2025 15:13:15 -0700 Subject: [PATCH 05/17] attempt a write / read test --- test-server/cpp-v2-server/main.cpp | 3 +++ test-server/cpp-v2-server/server.pid | 1 + test-server/cpp-v2-transition-server/main.cpp | 3 +++ test-server/cpp-v3-server/main.cpp | 3 +++ .../amazon/encryption/s3/RoundTripTests.java | 6 ++++-- .../software/amazon/encryption/s3/TestUtils.java | 8 ++++++++ test-server/java-v3-server/build.gradle.kts | 3 ++- .../encryption/s3/CreateClientOperationImpl.java | 12 ++++++++++++ .../encryption/s3/CreateClientOperationImpl.java | 10 ++++++++++ .../encryption/s3/CreateClientOperationImpl.java | 10 ++++++++++ test-server/php-v2-server/src/client.php | 6 ++++++ test-server/php-v2-transition-server/src/client.php | 5 +++++ test-server/php-v3-server/src/client.php | 7 +++++++ test-server/ruby-v2-server/lib/client_manager.rb | 2 ++ test-server/ruby-v3-server/lib/client_manager.rb | 4 +++- 15 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 test-server/cpp-v2-server/server.pid diff --git a/test-server/cpp-v2-server/main.cpp b/test-server/cpp-v2-server/main.cpp index c4f2c240..cbe06eb8 100644 --- a/test-server/cpp-v2-server/main.cpp +++ b/test-server/cpp-v2-server/main.cpp @@ -57,12 +57,15 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, std::string kms_key_id = request["config"]["keyMaterial"]["kmsKeyId"]; bool legacy1 = request["config"]["enableLegacyWrappingAlgorithms"]; bool legacy2 = request["config"]["enableLegacyUnauthenticatedModes"]; + bool inst_put = request["config"]["instructionFileConfig"]["enableInstructionFilePutObject"]; auto materials = std::make_shared(kms_key_id); CryptoConfigurationV2 config(materials); if (legacy1 || legacy2) config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY); + if (inst_put) + config.SetStorageMethod(StorageMethod::INSTRUCTION_FILE); auto encryption_client = std::make_shared(config); diff --git a/test-server/cpp-v2-server/server.pid b/test-server/cpp-v2-server/server.pid new file mode 100644 index 00000000..7e29010a --- /dev/null +++ b/test-server/cpp-v2-server/server.pid @@ -0,0 +1 @@ +45067 diff --git a/test-server/cpp-v2-transition-server/main.cpp b/test-server/cpp-v2-transition-server/main.cpp index 58d807ef..e2e96d20 100644 --- a/test-server/cpp-v2-transition-server/main.cpp +++ b/test-server/cpp-v2-transition-server/main.cpp @@ -82,12 +82,15 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, std::string kms_key_id = request["config"]["keyMaterial"]["kmsKeyId"]; bool legacy1 = request["config"]["enableLegacyWrappingAlgorithms"]; bool legacy2 = request["config"]["enableLegacyUnauthenticatedModes"]; + bool inst_put = request["config"]["instructionFileConfig"]["enableInstructionFilePutObject"]; auto materials = std::make_shared(kms_key_id); CryptoConfigurationV2 config(materials); if (legacy1 || legacy2) config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY); + if (inst_put) + config.SetStorageMethod(StorageMethod::INSTRUCTION_FILE); auto encryption_client = std::make_shared(config); diff --git a/test-server/cpp-v3-server/main.cpp b/test-server/cpp-v3-server/main.cpp index 59167078..5b17751d 100644 --- a/test-server/cpp-v3-server/main.cpp +++ b/test-server/cpp-v3-server/main.cpp @@ -72,12 +72,15 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, std::string kms_key_id = request["config"]["keyMaterial"]["kmsKeyId"]; bool legacy1 = request["config"]["enableLegacyWrappingAlgorithms"]; bool legacy2 = request["config"]["enableLegacyUnauthenticatedModes"]; + bool inst_put = request["config"]["instructionFileConfig"]["enableInstructionFilePutObject"]; auto materials = std::make_shared(kms_key_id); CryptoConfigurationV3 config(materials); if (legacy1 || legacy2) config.AllowLegacy(); + if (inst_put) + config.SetStorageMethod(StorageMethod::INSTRUCTION_FILE); std::string commitmentPolicy = get_config(request, "commitmentPolicy"); std::string encryptionAlgorithm = get_config(request, "encryptionAlgorithm"); diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index 0d5e2830..c7b016a6 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -471,8 +471,10 @@ public void instructionFileReadV2Format(TestUtils.LanguageServerTarget language) @ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}") @MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients") public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageServerTarget decLang) { - // Skip for now - if (true) { + if (INSTRUCTION_FILE_PUT_UNSUPPORTED.contains(encLang.getLanguageName())) { + return; + } + if (INSTRUCTION_FILE_GET_UNSUPPORTED.contains(decLang.getLanguageName())) { return; } if (KMS_INSTRUCTION_FILE_UNSUPPORTED.contains(encLang.getLanguageName())) { diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java index 0ed87fa3..e63ca091 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java @@ -102,6 +102,14 @@ public class TestUtils { public static final Set KMS_INSTRUCTION_FILE_UNSUPPORTED = Set.of(NET_V2_CURRENT, NET_V2_TRANSITION, NET_V3, PYTHON_V3); + // Go does not write with instruction files + public static final Set INSTRUCTION_FILE_PUT_UNSUPPORTED = + Set.of(GO_V3_CURRENT, GO_V3_TRANSITION, GO_V4); + + // Not implemented yet in Python. + public static final Set INSTRUCTION_FILE_GET_UNSUPPORTED = + Set.of(PYTHON_V3); + public static final Set CURRENT_VERSIONS = Set.of( JAVA_V3_CURRENT, diff --git a/test-server/java-v3-server/build.gradle.kts b/test-server/java-v3-server/build.gradle.kts index ca793e56..baae4947 100644 --- a/test-server/java-v3-server/build.gradle.kts +++ b/test-server/java-v3-server/build.gradle.kts @@ -14,7 +14,8 @@ dependencies { implementation("software.amazon.smithy.java:aws-server-restjson:$smithyJavaVersion") compileOnly("software.amazon.awssdk:aws-sdk-java:2.31.66") - implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.3.5") + // This MUST stay at 3.5.0 + implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.5.0") } // Use that application plugin to start the service via the `run` task. diff --git a/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index d992c435..1415fd01 100644 --- a/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v3-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -3,6 +3,7 @@ import software.amazon.awssdk.core.traits.Trait; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.encryption.s3.S3EncryptionClient; +import software.amazon.encryption.s3.internal.InstructionFileConfig; import software.amazon.encryption.s3.materials.AesKeyring; import software.amazon.encryption.s3.materials.Keyring; import software.amazon.encryption.s3.materials.KmsKeyring; @@ -54,6 +55,7 @@ private boolean onlyOneNonNull(Object... values) { @Override public CreateClientOutput createClient(CreateClientInput input, RequestContext context) { try { + // Key Material / Keyring Creation KeyMaterial key = input.getConfig().getKeyMaterial(); if (!onlyOneNonNull(key.getAesKey(), key.getKmsKeyId(), key.getRsaKey())) { throw new RuntimeException("KeyMaterial must be only one, non-null input!"); @@ -88,7 +90,17 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c } else { throw new RuntimeException("No KeyMaterial found!"); } + + // Client Creation + boolean instFilePut = false; + if (input.getConfig().getInstructionFileConfig() != null) { + instFilePut = input.getConfig().getInstructionFileConfig().isEnableInstructionFilePutObject(); + } S3Client s3Client = S3EncryptionClient.builder() + .instructionFileConfig(InstructionFileConfig.builder() + .instructionFileClient(S3Client.create()) + .enableInstructionFilePutObject(instFilePut) + .build()) .keyring(keyring) .build(); UUID uuid = UUID.randomUUID(); diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index d992c435..cd9042fe 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -88,7 +88,17 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c } else { throw new RuntimeException("No KeyMaterial found!"); } + + // Client Creation + boolean instFilePut = false; + if (input.getConfig().getInstructionFileConfig() != null) { + instFilePut = input.getConfig().getInstructionFileConfig().isEnableInstructionFilePutObject(); + } S3Client s3Client = S3EncryptionClient.builder() + .instructionFileConfig(InstructionFileConfig.builder() + .instructionFileClient(S3Client.create()) + .enableInstructionFilePutObject(instFilePut) + .build()) .keyring(keyring) .build(); UUID uuid = UUID.randomUUID(); diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index d992c435..cd9042fe 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -88,7 +88,17 @@ public CreateClientOutput createClient(CreateClientInput input, RequestContext c } else { throw new RuntimeException("No KeyMaterial found!"); } + + // Client Creation + boolean instFilePut = false; + if (input.getConfig().getInstructionFileConfig() != null) { + instFilePut = input.getConfig().getInstructionFileConfig().isEnableInstructionFilePutObject(); + } S3Client s3Client = S3EncryptionClient.builder() + .instructionFileConfig(InstructionFileConfig.builder() + .instructionFileClient(S3Client.create()) + .enableInstructionFilePutObject(instFilePut) + .build()) .keyring(keyring) .build(); UUID uuid = UUID.randomUUID(); diff --git a/test-server/php-v2-server/src/client.php b/test-server/php-v2-server/src/client.php index 44fe1b39..9c39d540 100644 --- a/test-server/php-v2-server/src/client.php +++ b/test-server/php-v2-server/src/client.php @@ -19,6 +19,11 @@ function handleCreateClient() $legacyAlgorithms = $configData["enableLegacyWrappingAlgorithms"] ?? false; $clientId = Uuid::uuid4()->toString(); $kmsKeyId = $keyMaterial["kmsKeyId"] ?? null; + $instFileConfig = $configData['instructionFileConfig'] ?? null; + $instFilePut = false; + if ($instFileConfig != null) { + $instFilePut = $instFileConfig['enableInstructionFilePutObject'] ?? false; + } if ($configData == []) { return GenericServerError("Invalid config in request body", 400); @@ -55,6 +60,7 @@ function handleCreateClient() ], 'kmsKeyId' => $kmsKeyId, 'legacy' => $legacyAlgorithms, + 'instFilePut' => $instFilePut, 'created' => time() ]; diff --git a/test-server/php-v2-transition-server/src/client.php b/test-server/php-v2-transition-server/src/client.php index 44fe1b39..beda557a 100644 --- a/test-server/php-v2-transition-server/src/client.php +++ b/test-server/php-v2-transition-server/src/client.php @@ -19,6 +19,10 @@ function handleCreateClient() $legacyAlgorithms = $configData["enableLegacyWrappingAlgorithms"] ?? false; $clientId = Uuid::uuid4()->toString(); $kmsKeyId = $keyMaterial["kmsKeyId"] ?? null; + $instFilePut = false; + if ($instFileConfig != null) { + $instFilePut = $instFileConfig['enableInstructionFilePutObject'] ?? false; + } if ($configData == []) { return GenericServerError("Invalid config in request body", 400); @@ -55,6 +59,7 @@ function handleCreateClient() ], 'kmsKeyId' => $kmsKeyId, 'legacy' => $legacyAlgorithms, + 'instFilePut' => $instFilePut, 'created' => time() ]; diff --git a/test-server/php-v3-server/src/client.php b/test-server/php-v3-server/src/client.php index 6c40f590..2c6204bb 100644 --- a/test-server/php-v3-server/src/client.php +++ b/test-server/php-v3-server/src/client.php @@ -19,6 +19,12 @@ function handleCreateClient() $legacyAlgorithms = $configData["enableLegacyWrappingAlgorithms"] ?? false; $clientId = Uuid::uuid4()->toString(); $kmsKeyId = $keyMaterial["kmsKeyId"] ?? null; + $instFileConfig = $configData['instructionFileConfig'] ?? null; + $instFilePut = false; + if ($instFileConfig != null) { + $instFilePut = $instFileConfig['enableInstructionFilePutObject'] ?? false; + } + if (empty($configData)) { return GenericServerError("Invalid config in request body", 400); @@ -55,6 +61,7 @@ function handleCreateClient() ], 'kmsKeyId' => $kmsKeyId, 'legacy' => $legacyAlgorithms, + 'instFilePut' => $instFilePut, 'created' => time() ]; diff --git a/test-server/ruby-v2-server/lib/client_manager.rb b/test-server/ruby-v2-server/lib/client_manager.rb index c6a25610..717003bf 100644 --- a/test-server/ruby-v2-server/lib/client_manager.rb +++ b/test-server/ruby-v2-server/lib/client_manager.rb @@ -16,6 +16,7 @@ def initialize def create_client(config) # Extract configuration kms_key_id = config.dig('keyMaterial', 'kmsKeyId') + inst_file_put = config.dig('instructionFileConfig', 'enableInstructionFilePutObject') raise 'KMS Key ID is required' if kms_key_id.nil? || kms_key_id.empty? @@ -25,6 +26,7 @@ def create_client(config) kms_client: @kms_client, key_wrap_schema: :kms_context, content_encryption_schema: :aes_gcm_no_padding, + envelope_location: inst_file_put ? :instruction_file : :metadata }.tap do |hash| if !config['enableLegacyWrappingAlgorithms'].nil? || !config['enableLegacyUnauthenticatedModes'].nil? legacy_modes = config['enableLegacyWrappingAlgorithms'] || config['enableLegacyUnauthenticatedModes'] diff --git a/test-server/ruby-v3-server/lib/client_manager.rb b/test-server/ruby-v3-server/lib/client_manager.rb index 7c125458..28bb17ac 100644 --- a/test-server/ruby-v3-server/lib/client_manager.rb +++ b/test-server/ruby-v3-server/lib/client_manager.rb @@ -16,7 +16,8 @@ def initialize def create_client(config) # Extract configuration kms_key_id = config.dig('keyMaterial', 'kmsKeyId') - + inst_file_put = config.dig('instructionFileConfig', 'enableInstructionFilePutObject') + raise 'KMS Key ID is required' if kms_key_id.nil? || kms_key_id.empty? # Create S3 encryption client configuration @@ -24,6 +25,7 @@ def create_client(config) kms_key_id: kms_key_id, kms_client: @kms_client, key_wrap_schema: :kms_context, + envelope_location: inst_file_put ? :instruction_file : :metadata # content_encryption_schema: :aes_gcm_no_padding, }.tap do |hash| if !config['commitmentPolicy'].nil? From baa2c2637253a4de07b9bbc53e1c12dce03320a3 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Thu, 30 Oct 2025 17:05:00 -0700 Subject: [PATCH 06/17] java --- .../software/amazon/encryption/s3/CreateClientOperationImpl.java | 1 + .../software/amazon/encryption/s3/CreateClientOperationImpl.java | 1 + 2 files changed, 2 insertions(+) diff --git a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index cd9042fe..8622f1ac 100644 --- a/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v3-transition-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -2,6 +2,7 @@ import software.amazon.awssdk.core.traits.Trait; import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.encryption.s3.internal.InstructionFileConfig; import software.amazon.encryption.s3.S3EncryptionClient; import software.amazon.encryption.s3.materials.AesKeyring; import software.amazon.encryption.s3.materials.Keyring; diff --git a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java index cd9042fe..8622f1ac 100644 --- a/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java +++ b/test-server/java-v4-server/src/main/java/software/amazon/encryption/s3/CreateClientOperationImpl.java @@ -2,6 +2,7 @@ import software.amazon.awssdk.core.traits.Trait; import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.encryption.s3.internal.InstructionFileConfig; import software.amazon.encryption.s3.S3EncryptionClient; import software.amazon.encryption.s3.materials.AesKeyring; import software.amazon.encryption.s3.materials.Keyring; From 9ec8f690490f3c8f7bfcd759214ace245d3c567a Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Mon, 3 Nov 2025 11:54:29 -0800 Subject: [PATCH 07/17] write read RT for Java, Ruby --- .../amazon/encryption/s3/RoundTripTests.java | 41 +++++++++++-------- .../amazon/encryption/s3/TestUtils.java | 35 ++++++++-------- .../ruby-v3-server/lib/client_manager.rb | 14 ++++++- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index c7b016a6..abd94b96 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -16,18 +16,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Stream; import com.amazonaws.services.s3.AmazonS3EncryptionClientV2; import com.amazonaws.services.s3.AmazonS3EncryptionV2; import com.amazonaws.services.s3.model.CryptoConfigurationV2; -import com.amazonaws.services.s3.model.EncryptionMaterials; import com.amazonaws.services.s3.model.KMSEncryptionMaterials; -import com.amazonaws.services.s3.model.StaticEncryptionMaterialsProvider; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.opentest4j.TestAbortedException; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectResponse; @@ -35,6 +32,7 @@ import software.amazon.encryption.s3.model.CommitmentPolicy; import software.amazon.encryption.s3.model.CreateClientInput; import software.amazon.encryption.s3.model.CreateClientOutput; +import software.amazon.encryption.s3.model.EncryptionAlgorithm; import software.amazon.encryption.s3.model.GetObjectInput; import software.amazon.encryption.s3.model.GetObjectOutput; import software.amazon.encryption.s3.model.InstructionFileConfig; @@ -48,7 +46,6 @@ import com.amazonaws.services.s3.model.CryptoConfiguration; import com.amazonaws.services.s3.model.CryptoMode; import com.amazonaws.services.s3.model.CryptoStorageMode; -import software.amazon.encryption.s3.TestUtils.*; import com.amazonaws.services.s3.model.EncryptionMaterialsProvider; import com.amazonaws.services.s3.model.KMSEncryptionMaterialsProvider; @@ -472,16 +469,22 @@ public void instructionFileReadV2Format(TestUtils.LanguageServerTarget language) @MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients") public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageServerTarget decLang) { if (INSTRUCTION_FILE_PUT_UNSUPPORTED.contains(encLang.getLanguageName())) { - return; + throw new TestAbortedException("not testing " + encLang.getLanguageName()); } if (INSTRUCTION_FILE_GET_UNSUPPORTED.contains(decLang.getLanguageName())) { - return; + throw new TestAbortedException("not testing " + encLang.getLanguageName()); } if (KMS_INSTRUCTION_FILE_UNSUPPORTED.contains(encLang.getLanguageName())) { - return; + throw new TestAbortedException("not testing " + encLang.getLanguageName()); } if (KMS_INSTRUCTION_FILE_UNSUPPORTED.contains(decLang.getLanguageName())) { - return; + throw new TestAbortedException("not testing " + encLang.getLanguageName()); + } + if (!INSTRUCTION_FILE_ROUNDTRIP_SUPPORTED.contains(encLang.getLanguageName())) { + throw new TestAbortedException("not testing " + encLang.getLanguageName()); + } + if (!INSTRUCTION_FILE_ROUNDTRIP_SUPPORTED.contains(decLang.getLanguageName())) { + throw new TestAbortedException("not testing " + decLang.getLanguageName()); } S3ECTestServerClient encClient = testServerClientFor(encLang); S3ECTestServerClient decClient = testServerClientFor(decLang); @@ -497,6 +500,7 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe .enableInstructionFilePutObject(true) .build()) .commitmentPolicy(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT) + .encryptionAlgorithm(EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF) .build()) .build()); String encS3ECId = encOutput.getClientId(); @@ -518,14 +522,17 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe // Assert using Java plaintext client that an instruction file exists ResponseBytes ptInstFile; - try (S3Client ptS3Client = S3Client.create()) { - ptInstFile = ptS3Client.getObjectAsBytes(builder -> builder - .bucket(BUCKET) - .key(objectKey + ".instruction") - .build()); - } - // Check for inst file key - assertTrue(ptInstFile.response().metadata().containsKey("x-amz-crypto-instr-file")); + try (S3Client ptS3Client = S3Client.create()) { + ptInstFile = ptS3Client.getObjectAsBytes(builder -> builder + .bucket(BUCKET) + .key(objectKey + ".instruction") + .build()); + } + // Check for inst file key + if (!encLang.getLanguageName().contains("Ruby")) { + // Ruby doesn't include it :( + assertTrue(ptInstFile.response().metadata().containsKey("x-amz-crypto-instr-file")); + } assertFalse(ptInstFile.asUtf8String().isEmpty()); // Read should be enabled by default diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java index e63ca091..145b2429 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java @@ -22,32 +22,29 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.ObjectMetadata; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.junit.jupiter.params.provider.Arguments; import com.amazonaws.regions.Region; import com.amazonaws.regions.Regions; -import software.amazon.smithy.java.aws.client.restjson.RestJsonClientProtocol; -import software.amazon.smithy.java.client.core.ClientConfig; -import software.amazon.smithy.java.client.core.ClientProtocol; -import software.amazon.smithy.java.client.core.endpoint.EndpointResolver; -import software.amazon.encryption.s3.client.S3ECTestServerClient; import software.amazon.encryption.s3.model.EncryptionAlgorithm; import software.amazon.encryption.s3.model.GetObjectInput; import software.amazon.encryption.s3.model.GetObjectOutput; import software.amazon.encryption.s3.model.PutObjectInput; import software.amazon.encryption.s3.model.PutObjectOutput; -import software.amazon.encryption.s3.model.S3ECConfig; -import software.amazon.encryption.s3.model.S3ECTestServerApiService; import software.amazon.encryption.s3.model.S3EncryptionClientError; +import software.amazon.smithy.java.aws.client.restjson.RestJsonClientProtocol; +import software.amazon.smithy.java.client.core.ClientConfig; +import software.amazon.smithy.java.client.core.ClientProtocol; +import software.amazon.smithy.java.client.core.endpoint.EndpointResolver; +import software.amazon.encryption.s3.client.S3ECTestServerClient; +import software.amazon.encryption.s3.model.S3ECTestServerApiService; import software.amazon.smithy.java.http.api.HttpRequest; import software.amazon.smithy.java.http.api.HttpResponse; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.GetObjectMetadataRequest; - public class TestUtils { // Version name constants @@ -110,6 +107,10 @@ public class TestUtils { public static final Set INSTRUCTION_FILE_GET_UNSUPPORTED = Set.of(PYTHON_V3); + // Until all languages work, just test these for now + public static final Set INSTRUCTION_FILE_ROUNDTRIP_SUPPORTED = + Set.of(JAVA_V3_CURRENT, JAVA_V3_TRANSITION, RUBY_V2_TRANSITION, RUBY_V3); + public static final Set CURRENT_VERSIONS = Set.of( JAVA_V3_CURRENT, @@ -299,7 +300,7 @@ public static List metadataMapToList(Map md) { public static void validateServersRunning() { for (LanguageServerTarget server : serverMap.values()) { if (!serverListening(server.getServerURI())) { - throw new RuntimeException(String.format("Test Server for %s is not running at endpoint: %s", + throw new RuntimeException(String.format("Test Server for %s is not running at endpoint: %s", server.getLanguageName(), server.getServerURI())); } } @@ -443,7 +444,7 @@ public static EncryptionAlgorithm GetEncryptionAlgorithm(String objectKey) return EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; } } - + throw new RuntimeException("Need to support instruction files!"); } @@ -469,7 +470,7 @@ public static void Encrypt( crossLanguageObjects.add(objectKey); } - + public static void Decrypt( S3ECTestServerClient client, String S3ECId, List crossLanguageObjects, @@ -481,7 +482,7 @@ public static void Decrypt( .bucket(TestUtils.BUCKET) .key(objectKey) .build()); - + // Then: Pass assertEquals(objectKey, new String(output.getBody().array())); assertEquals( @@ -491,7 +492,7 @@ public static void Decrypt( ); } } - + public static void Decrypt_fails( S3ECTestServerClient client, String S3ECId, List crossLanguageObjects, diff --git a/test-server/ruby-v3-server/lib/client_manager.rb b/test-server/ruby-v3-server/lib/client_manager.rb index dd181786..e70c1237 100644 --- a/test-server/ruby-v3-server/lib/client_manager.rb +++ b/test-server/ruby-v3-server/lib/client_manager.rb @@ -17,6 +17,16 @@ def create_client(config) # Extract configuration kms_key_id = config.dig('keyMaterial', 'kmsKeyId') inst_file_put = config.dig('instructionFileConfig', 'enableInstructionFilePutObject') + content_alg = config.dig('encryptionAlgorithm') + + # translate between canonical AlgSuite and Ruby symbols + if content_alg.nil? || content_alg == 'ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY' + content_alg = :aes_gcm_with_commitment + elsif content_alg == 'ALG_AES_256_GCM_IV12_TAG16_NO_KDF' + content_alg = :aes_gcm_no_padding + else + raise 'Unknown content encryption algorithm provided: ' + content_alg + end raise 'KMS Key ID is required' if kms_key_id.nil? || kms_key_id.empty? @@ -25,8 +35,8 @@ def create_client(config) kms_key_id: kms_key_id, kms_client: @kms_client, key_wrap_schema: :kms_context, - envelope_location: inst_file_put ? :instruction_file : :metadata - # content_encryption_schema: :aes_gcm_no_padding, + envelope_location: inst_file_put ? :instruction_file : :metadata, + content_encryption_schema: content_alg }.tap do |hash| if !config['commitmentPolicy'].nil? hash[:commitment_policy] = case config['commitmentPolicy'] From 443cd38f33da41966cd097fa5612776b017c1201 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Mon, 3 Nov 2025 14:07:10 -0800 Subject: [PATCH 08/17] add Go --- .../java/software/amazon/encryption/s3/TestUtils.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java index 145b2429..8767f9c9 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java @@ -97,11 +97,11 @@ public class TestUtils { // .NET only supports decrypting instruction files using AES and RSA. // Python MUST support decrypting KMS instruction files, but does not yet. public static final Set KMS_INSTRUCTION_FILE_UNSUPPORTED = - Set.of(NET_V2_CURRENT, NET_V2_TRANSITION, NET_V3, PYTHON_V3); + Set.of(NET_V2_CURRENT, NET_V2_TRANSITION, NET_V3); // Go does not write with instruction files public static final Set INSTRUCTION_FILE_PUT_UNSUPPORTED = - Set.of(GO_V3_CURRENT, GO_V3_TRANSITION, GO_V4); + Set.of(GO_V3_CURRENT, GO_V3_TRANSITION, GO_V4, PYTHON_V3); // Not implemented yet in Python. public static final Set INSTRUCTION_FILE_GET_UNSUPPORTED = @@ -109,7 +109,11 @@ public class TestUtils { // Until all languages work, just test these for now public static final Set INSTRUCTION_FILE_ROUNDTRIP_SUPPORTED = - Set.of(JAVA_V3_CURRENT, JAVA_V3_TRANSITION, RUBY_V2_TRANSITION, RUBY_V3); + Set.of(JAVA_V3_CURRENT, JAVA_V3_TRANSITION, RUBY_V2_TRANSITION, RUBY_V3 + // PHP doesn't work yet +// PHP_V2_CURRENT, PHP_V2_TRANSITION, PHP_V3) + , GO_V3_CURRENT, GO_V4 + ); public static final Set CURRENT_VERSIONS = Set.of( From c4d308807809fe7204e98fed4f611678664de03f Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Mon, 3 Nov 2025 15:29:10 -0800 Subject: [PATCH 09/17] fixup CPP servers --- test-server/cpp-v2-server/main.cpp | 6 +++++- test-server/cpp-v2-transition-server/main.cpp | 6 +++++- test-server/cpp-v3-server/main.cpp | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/test-server/cpp-v2-server/main.cpp b/test-server/cpp-v2-server/main.cpp index cbe06eb8..a2b05810 100644 --- a/test-server/cpp-v2-server/main.cpp +++ b/test-server/cpp-v2-server/main.cpp @@ -57,7 +57,11 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, std::string kms_key_id = request["config"]["keyMaterial"]["kmsKeyId"]; bool legacy1 = request["config"]["enableLegacyWrappingAlgorithms"]; bool legacy2 = request["config"]["enableLegacyUnauthenticatedModes"]; - bool inst_put = request["config"]["instructionFileConfig"]["enableInstructionFilePutObject"]; + bool inst_put = false; + if (request["config"].contains("instructionFileConfig") && + request["config"]["instructionFileConfig"].contains("enableInstructionFilePutObject")) { + inst_put = request["config"]["instructionFileConfig"]["enableInstructionFilePutObject"]; + } auto materials = std::make_shared(kms_key_id); diff --git a/test-server/cpp-v2-transition-server/main.cpp b/test-server/cpp-v2-transition-server/main.cpp index e2e96d20..1fcedc3c 100644 --- a/test-server/cpp-v2-transition-server/main.cpp +++ b/test-server/cpp-v2-transition-server/main.cpp @@ -82,7 +82,11 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, std::string kms_key_id = request["config"]["keyMaterial"]["kmsKeyId"]; bool legacy1 = request["config"]["enableLegacyWrappingAlgorithms"]; bool legacy2 = request["config"]["enableLegacyUnauthenticatedModes"]; - bool inst_put = request["config"]["instructionFileConfig"]["enableInstructionFilePutObject"]; + bool inst_put = false; + if (request["config"].contains("instructionFileConfig") && + request["config"]["instructionFileConfig"].contains("enableInstructionFilePutObject")) { + inst_put = request["config"]["instructionFileConfig"]["enableInstructionFilePutObject"]; + } auto materials = std::make_shared(kms_key_id); diff --git a/test-server/cpp-v3-server/main.cpp b/test-server/cpp-v3-server/main.cpp index 5b17751d..1f74974c 100644 --- a/test-server/cpp-v3-server/main.cpp +++ b/test-server/cpp-v3-server/main.cpp @@ -72,7 +72,11 @@ MHD_Result handle_create_client(struct MHD_Connection *connection, std::string kms_key_id = request["config"]["keyMaterial"]["kmsKeyId"]; bool legacy1 = request["config"]["enableLegacyWrappingAlgorithms"]; bool legacy2 = request["config"]["enableLegacyUnauthenticatedModes"]; - bool inst_put = request["config"]["instructionFileConfig"]["enableInstructionFilePutObject"]; + bool inst_put = false; + if (request["config"].contains("instructionFileConfig") && + request["config"]["instructionFileConfig"].contains("enableInstructionFilePutObject")) { + inst_put = request["config"]["instructionFileConfig"]["enableInstructionFilePutObject"]; + } auto materials = std::make_shared(kms_key_id); From d3c174ff44c905d35df27ac83574da2965ca3cdb Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Mon, 3 Nov 2025 16:00:44 -0800 Subject: [PATCH 10/17] disable Python read --- .../java/software/amazon/encryption/s3/RoundTripTests.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index abd94b96..9bbc5bb0 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -428,7 +428,10 @@ public void kmsV1LegacyFailsWhenLegacyDisabled(TestUtils.LanguageServerTarget la @MethodSource("software.amazon.encryption.s3.TestUtils#clientsForTest") public void instructionFileReadV2Format(TestUtils.LanguageServerTarget language) { if (KMS_INSTRUCTION_FILE_UNSUPPORTED.contains(language.getLanguageName())) { - return; + throw new TestAbortedException(String.format("%s does not support KMS instruction files", language.getLanguageName())); + } + if (INSTRUCTION_FILE_GET_UNSUPPORTED.contains(language.getLanguageName())) { + throw new TestAbortedException(String.format("%s does not support instruction file Gets", language.getLanguageName())); } S3ECTestServerClient client = testServerClientFor(language); final String objectKey = appendTestSuffix("read-instruction-file-v2-" + language); From 6e9bafa1c4ec4787db838f06f2dfea764a88f2dd Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Mon, 3 Nov 2025 16:05:19 -0800 Subject: [PATCH 11/17] fix ruby kc alg --- test-server/ruby-v3-server/lib/client_manager.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-server/ruby-v3-server/lib/client_manager.rb b/test-server/ruby-v3-server/lib/client_manager.rb index e70c1237..a6fb551f 100644 --- a/test-server/ruby-v3-server/lib/client_manager.rb +++ b/test-server/ruby-v3-server/lib/client_manager.rb @@ -21,7 +21,7 @@ def create_client(config) # translate between canonical AlgSuite and Ruby symbols if content_alg.nil? || content_alg == 'ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY' - content_alg = :aes_gcm_with_commitment + content_alg = :alg_aes_256_gcm_hkdf_sha512_commit_key elsif content_alg == 'ALG_AES_256_GCM_IV12_TAG16_NO_KDF' content_alg = :aes_gcm_no_padding else From 5e68196d479fe5c32c3472d0677ed893b33be814 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Mon, 3 Nov 2025 17:37:25 -0800 Subject: [PATCH 12/17] test C++ for fun and for profit --- .../amazon/encryption/s3/TestUtils.java | 205 +++++++++--------- 1 file changed, 104 insertions(+), 101 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java index 8767f9c9..0ab226a4 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java @@ -113,6 +113,9 @@ public class TestUtils { // PHP doesn't work yet // PHP_V2_CURRENT, PHP_V2_TRANSITION, PHP_V3) , GO_V3_CURRENT, GO_V4 + // These get skipped anyway b/c KMS isn't supported + , NET_V2_CURRENT, NET_V3 + , CPP_V2_CURRENT, CPP_V2_TRANSITION, CPP_V3 ); public static final Set CURRENT_VERSIONS = @@ -302,12 +305,12 @@ public static List metadataMapToList(Map md) { * @throws RuntimeException if any server is not running */ public static void validateServersRunning() { - for (LanguageServerTarget server : serverMap.values()) { - if (!serverListening(server.getServerURI())) { - throw new RuntimeException(String.format("Test Server for %s is not running at endpoint: %s", - server.getLanguageName(), server.getServerURI())); - } - } +// for (LanguageServerTarget server : serverMap.values()) { +// if (!serverListening(server.getServerURI())) { +// throw new RuntimeException(String.format("Test Server for %s is not running at endpoint: %s", +// server.getLanguageName(), server.getServerURI())); +// } +// } } /** @@ -431,99 +434,99 @@ public static String appendTestSuffix(final String s) { return stringBuilder.toString(); } - private static AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient(); - public static EncryptionAlgorithm GetEncryptionAlgorithm(String objectKey) - { - ObjectMetadata metadata = s3Client.getObjectMetadata(TestUtils.BUCKET, objectKey); - Map userMetadata = metadata.getUserMetadata(); - - // This is optimized to not need to go to the instruction files for commit_key - if (userMetadata.containsKey("x-amz-c")) { - return EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; - } else if (userMetadata.containsKey("x-amz-cek-alg")) { - String cek = userMetadata.get("x-amz-cek-alg"); - if (cek.contains("CBC")) { - return EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF; - } else if (cek.contains("GCM")) { - return EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; - } - } - - throw new RuntimeException("Need to support instruction files!"); - } - - public static void Encrypt( - S3ECTestServerClient client, - String S3ECId, - String objectKey, - List crossLanguageObjects, - EncryptionAlgorithm expectedEncryptionAlgorithm - ) { - PutObjectOutput foo = client.putObject(PutObjectInput.builder() - .clientID(S3ECId) - .key(objectKey) - .bucket(TestUtils.BUCKET) - .body(ByteBuffer.wrap(objectKey.getBytes(StandardCharsets.UTF_8))) - .build()); - - assertEquals( - expectedEncryptionAlgorithm, - GetEncryptionAlgorithm(objectKey), - "When encrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm - ); - - crossLanguageObjects.add(objectKey); - } - - public static void Decrypt( - S3ECTestServerClient client, - String S3ECId, List crossLanguageObjects, - EncryptionAlgorithm expectedEncryptionAlgorithm - ) { - for (String objectKey : crossLanguageObjects) { - GetObjectOutput output = client.getObject(GetObjectInput.builder() - .clientID(S3ECId) - .bucket(TestUtils.BUCKET) - .key(objectKey) - .build()); - - // Then: Pass - assertEquals(objectKey, new String(output.getBody().array())); - assertEquals( - expectedEncryptionAlgorithm, - GetEncryptionAlgorithm(objectKey), - "When decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm - ); - } - } - - public static void Decrypt_fails( - S3ECTestServerClient client, - String S3ECId, List crossLanguageObjects, - EncryptionAlgorithm expectedEncryptionAlgorithm - ) { - List successfulDecrypt = new ArrayList<>(); - for (String objectKey : crossLanguageObjects) { - try { - - assertEquals( - expectedEncryptionAlgorithm, - GetEncryptionAlgorithm(objectKey), - "Before decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm - ); - GetObjectOutput output = client.getObject(GetObjectInput.builder() - .clientID(S3ECId) - .bucket(TestUtils.BUCKET) - .key(objectKey) - .build()); - // It should fail to decrypt - successfulDecrypt.add(objectKey); - } catch (S3EncryptionClientError e) { - // This is a success - // TODO, add the failure message - } - } - - assertEquals(successfulDecrypt.size(), 0, "Decryption should have failed:" + String.join(",", successfulDecrypt)); - } +// private static AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient(); +// public static EncryptionAlgorithm GetEncryptionAlgorithm(String objectKey) +// { +// ObjectMetadata metadata = s3Client.getObjectMetadata(TestUtils.BUCKET, objectKey); +// Map userMetadata = metadata.getUserMetadata(); +// +// // This is optimized to not need to go to the instruction files for commit_key +// if (userMetadata.containsKey("x-amz-c")) { +// return EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; +// } else if (userMetadata.containsKey("x-amz-cek-alg")) { +// String cek = userMetadata.get("x-amz-cek-alg"); +// if (cek.contains("CBC")) { +// return EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF; +// } else if (cek.contains("GCM")) { +// return EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; +// } +// } +// +// throw new RuntimeException("Need to support instruction files!"); +// } +// +// public static void Encrypt( +// S3ECTestServerClient client, +// String S3ECId, +// String objectKey, +// List crossLanguageObjects, +// EncryptionAlgorithm expectedEncryptionAlgorithm +// ) { +// PutObjectOutput foo = client.putObject(PutObjectInput.builder() +// .clientID(S3ECId) +// .key(objectKey) +// .bucket(TestUtils.BUCKET) +// .body(ByteBuffer.wrap(objectKey.getBytes(StandardCharsets.UTF_8))) +// .build()); +// +// assertEquals( +// expectedEncryptionAlgorithm, +// GetEncryptionAlgorithm(objectKey), +// "When encrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm +// ); +// +// crossLanguageObjects.add(objectKey); +// } +// +// public static void Decrypt( +// S3ECTestServerClient client, +// String S3ECId, List crossLanguageObjects, +// EncryptionAlgorithm expectedEncryptionAlgorithm +// ) { +// for (String objectKey : crossLanguageObjects) { +// GetObjectOutput output = client.getObject(GetObjectInput.builder() +// .clientID(S3ECId) +// .bucket(TestUtils.BUCKET) +// .key(objectKey) +// .build()); +// +// // Then: Pass +// assertEquals(objectKey, new String(output.getBody().array())); +// assertEquals( +// expectedEncryptionAlgorithm, +// GetEncryptionAlgorithm(objectKey), +// "When decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm +// ); +// } +// } +// +// public static void Decrypt_fails( +// S3ECTestServerClient client, +// String S3ECId, List crossLanguageObjects, +// EncryptionAlgorithm expectedEncryptionAlgorithm +// ) { +// List successfulDecrypt = new ArrayList<>(); +// for (String objectKey : crossLanguageObjects) { +// try { +// +// assertEquals( +// expectedEncryptionAlgorithm, +// GetEncryptionAlgorithm(objectKey), +// "Before decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm +// ); +// GetObjectOutput output = client.getObject(GetObjectInput.builder() +// .clientID(S3ECId) +// .bucket(TestUtils.BUCKET) +// .key(objectKey) +// .build()); +// // It should fail to decrypt +// successfulDecrypt.add(objectKey); +// } catch (S3EncryptionClientError e) { +// // This is a success +// // TODO, add the failure message +// } +// } +// +// assertEquals(successfulDecrypt.size(), 0, "Decryption should have failed:" + String.join(",", successfulDecrypt)); +// } } From 65fbb1c9f258d43476a0c6479b4c16d08f8c2510 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Mon, 3 Nov 2025 17:38:29 -0800 Subject: [PATCH 13/17] oopsie --- .../amazon/encryption/s3/TestUtils.java | 202 +++++++++--------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java index 0ab226a4..68902800 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java @@ -305,12 +305,12 @@ public static List metadataMapToList(Map md) { * @throws RuntimeException if any server is not running */ public static void validateServersRunning() { -// for (LanguageServerTarget server : serverMap.values()) { -// if (!serverListening(server.getServerURI())) { -// throw new RuntimeException(String.format("Test Server for %s is not running at endpoint: %s", -// server.getLanguageName(), server.getServerURI())); -// } -// } + for (LanguageServerTarget server : serverMap.values()) { + if (!serverListening(server.getServerURI())) { + throw new RuntimeException(String.format("Test Server for %s is not running at endpoint: %s", + server.getLanguageName(), server.getServerURI())); + } + } } /** @@ -434,99 +434,99 @@ public static String appendTestSuffix(final String s) { return stringBuilder.toString(); } -// private static AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient(); -// public static EncryptionAlgorithm GetEncryptionAlgorithm(String objectKey) -// { -// ObjectMetadata metadata = s3Client.getObjectMetadata(TestUtils.BUCKET, objectKey); -// Map userMetadata = metadata.getUserMetadata(); -// -// // This is optimized to not need to go to the instruction files for commit_key -// if (userMetadata.containsKey("x-amz-c")) { -// return EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; -// } else if (userMetadata.containsKey("x-amz-cek-alg")) { -// String cek = userMetadata.get("x-amz-cek-alg"); -// if (cek.contains("CBC")) { -// return EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF; -// } else if (cek.contains("GCM")) { -// return EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; -// } -// } -// -// throw new RuntimeException("Need to support instruction files!"); -// } -// -// public static void Encrypt( -// S3ECTestServerClient client, -// String S3ECId, -// String objectKey, -// List crossLanguageObjects, -// EncryptionAlgorithm expectedEncryptionAlgorithm -// ) { -// PutObjectOutput foo = client.putObject(PutObjectInput.builder() -// .clientID(S3ECId) -// .key(objectKey) -// .bucket(TestUtils.BUCKET) -// .body(ByteBuffer.wrap(objectKey.getBytes(StandardCharsets.UTF_8))) -// .build()); -// -// assertEquals( -// expectedEncryptionAlgorithm, -// GetEncryptionAlgorithm(objectKey), -// "When encrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm -// ); -// -// crossLanguageObjects.add(objectKey); -// } -// -// public static void Decrypt( -// S3ECTestServerClient client, -// String S3ECId, List crossLanguageObjects, -// EncryptionAlgorithm expectedEncryptionAlgorithm -// ) { -// for (String objectKey : crossLanguageObjects) { -// GetObjectOutput output = client.getObject(GetObjectInput.builder() -// .clientID(S3ECId) -// .bucket(TestUtils.BUCKET) -// .key(objectKey) -// .build()); -// -// // Then: Pass -// assertEquals(objectKey, new String(output.getBody().array())); -// assertEquals( -// expectedEncryptionAlgorithm, -// GetEncryptionAlgorithm(objectKey), -// "When decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm -// ); -// } -// } -// -// public static void Decrypt_fails( -// S3ECTestServerClient client, -// String S3ECId, List crossLanguageObjects, -// EncryptionAlgorithm expectedEncryptionAlgorithm -// ) { -// List successfulDecrypt = new ArrayList<>(); -// for (String objectKey : crossLanguageObjects) { -// try { -// -// assertEquals( -// expectedEncryptionAlgorithm, -// GetEncryptionAlgorithm(objectKey), -// "Before decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm -// ); -// GetObjectOutput output = client.getObject(GetObjectInput.builder() -// .clientID(S3ECId) -// .bucket(TestUtils.BUCKET) -// .key(objectKey) -// .build()); -// // It should fail to decrypt -// successfulDecrypt.add(objectKey); -// } catch (S3EncryptionClientError e) { -// // This is a success -// // TODO, add the failure message -// } -// } -// -// assertEquals(successfulDecrypt.size(), 0, "Decryption should have failed:" + String.join(",", successfulDecrypt)); -// } + private static AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient(); + public static EncryptionAlgorithm GetEncryptionAlgorithm(String objectKey) + { + ObjectMetadata metadata = s3Client.getObjectMetadata(TestUtils.BUCKET, objectKey); + Map userMetadata = metadata.getUserMetadata(); + + // This is optimized to not need to go to the instruction files for commit_key + if (userMetadata.containsKey("x-amz-c")) { + return EncryptionAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY; + } else if (userMetadata.containsKey("x-amz-cek-alg")) { + String cek = userMetadata.get("x-amz-cek-alg"); + if (cek.contains("CBC")) { + return EncryptionAlgorithm.ALG_AES_256_CBC_IV16_NO_KDF; + } else if (cek.contains("GCM")) { + return EncryptionAlgorithm.ALG_AES_256_GCM_IV12_TAG16_NO_KDF; + } + } + + throw new RuntimeException("Need to support instruction files!"); + } + + public static void Encrypt( + S3ECTestServerClient client, + String S3ECId, + String objectKey, + List crossLanguageObjects, + EncryptionAlgorithm expectedEncryptionAlgorithm + ) { + PutObjectOutput foo = client.putObject(PutObjectInput.builder() + .clientID(S3ECId) + .key(objectKey) + .bucket(TestUtils.BUCKET) + .body(ByteBuffer.wrap(objectKey.getBytes(StandardCharsets.UTF_8))) + .build()); + + assertEquals( + expectedEncryptionAlgorithm, + GetEncryptionAlgorithm(objectKey), + "When encrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm + ); + + crossLanguageObjects.add(objectKey); + } + + public static void Decrypt( + S3ECTestServerClient client, + String S3ECId, List crossLanguageObjects, + EncryptionAlgorithm expectedEncryptionAlgorithm + ) { + for (String objectKey : crossLanguageObjects) { + GetObjectOutput output = client.getObject(GetObjectInput.builder() + .clientID(S3ECId) + .bucket(TestUtils.BUCKET) + .key(objectKey) + .build()); + + // Then: Pass + assertEquals(objectKey, new String(output.getBody().array())); + assertEquals( + expectedEncryptionAlgorithm, + GetEncryptionAlgorithm(objectKey), + "When decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm + ); + } + } + + public static void Decrypt_fails( + S3ECTestServerClient client, + String S3ECId, List crossLanguageObjects, + EncryptionAlgorithm expectedEncryptionAlgorithm + ) { + List successfulDecrypt = new ArrayList<>(); + for (String objectKey : crossLanguageObjects) { + try { + + assertEquals( + expectedEncryptionAlgorithm, + GetEncryptionAlgorithm(objectKey), + "Before decrypting the EncryptionAlgorithm does not match the expected value: " + expectedEncryptionAlgorithm + ); + GetObjectOutput output = client.getObject(GetObjectInput.builder() + .clientID(S3ECId) + .bucket(TestUtils.BUCKET) + .key(objectKey) + .build()); + // It should fail to decrypt + successfulDecrypt.add(objectKey); + } catch (S3EncryptionClientError e) { + // This is a success + // TODO, add the failure message + } + } + + assertEquals(successfulDecrypt.size(), 0, "Decryption should have failed:" + String.join(",", successfulDecrypt)); + } } From f2b478d2fd3dedf2cec92b3c932e9c0db9bae3f1 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Mon, 3 Nov 2025 18:32:00 -0800 Subject: [PATCH 14/17] tweak support logic now that most are supported --- .../amazon/encryption/s3/TestUtils.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java index 68902800..dc82455b 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/TestUtils.java @@ -101,22 +101,17 @@ public class TestUtils { // Go does not write with instruction files public static final Set INSTRUCTION_FILE_PUT_UNSUPPORTED = - Set.of(GO_V3_CURRENT, GO_V3_TRANSITION, GO_V4, PYTHON_V3); + Set.of(GO_V3_CURRENT, GO_V3_TRANSITION, GO_V4, PYTHON_V3 + // Apparently C++ V2 Current does not work, even though it should + , CPP_V2_CURRENT); // Not implemented yet in Python. public static final Set INSTRUCTION_FILE_GET_UNSUPPORTED = Set.of(PYTHON_V3); - // Until all languages work, just test these for now - public static final Set INSTRUCTION_FILE_ROUNDTRIP_SUPPORTED = - Set.of(JAVA_V3_CURRENT, JAVA_V3_TRANSITION, RUBY_V2_TRANSITION, RUBY_V3 - // PHP doesn't work yet -// PHP_V2_CURRENT, PHP_V2_TRANSITION, PHP_V3) - , GO_V3_CURRENT, GO_V4 - // These get skipped anyway b/c KMS isn't supported - , NET_V2_CURRENT, NET_V3 - , CPP_V2_CURRENT, CPP_V2_TRANSITION, CPP_V3 - ); + // PHP doesn't work but it should, temporarily disable + public static final Set INSTRUCTION_FILE_ROUNDTRIP_TEMP_UNSUPPORTED = + Set.of(PHP_V2_CURRENT, PHP_V2_TRANSITION, PHP_V3); public static final Set CURRENT_VERSIONS = Set.of( From 1ea0b5729f8d11d5a0e2377fa153e71c9c50a7e7 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Tue, 4 Nov 2025 09:04:15 -0800 Subject: [PATCH 15/17] oopsie --- .../java/software/amazon/encryption/s3/RoundTripTests.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java index 9bbc5bb0..a63e1518 100644 --- a/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java +++ b/test-server/java-tests/src/it/java/software/amazon/encryption/s3/RoundTripTests.java @@ -483,12 +483,9 @@ public void instructionFileWriteAndRead(LanguageServerTarget encLang, LanguageSe if (KMS_INSTRUCTION_FILE_UNSUPPORTED.contains(decLang.getLanguageName())) { throw new TestAbortedException("not testing " + encLang.getLanguageName()); } - if (!INSTRUCTION_FILE_ROUNDTRIP_SUPPORTED.contains(encLang.getLanguageName())) { + if (INSTRUCTION_FILE_ROUNDTRIP_TEMP_UNSUPPORTED.contains(encLang.getLanguageName())) { throw new TestAbortedException("not testing " + encLang.getLanguageName()); } - if (!INSTRUCTION_FILE_ROUNDTRIP_SUPPORTED.contains(decLang.getLanguageName())) { - throw new TestAbortedException("not testing " + decLang.getLanguageName()); - } S3ECTestServerClient encClient = testServerClientFor(encLang); S3ECTestServerClient decClient = testServerClientFor(decLang); final String objectKey = appendTestSuffix(String.format("write-%s-read-%s-instruction-file", encLang.getLanguageName(), decLang.getLanguageName())); From d84902f26057488171adbd35491f70a1ad3961d8 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Tue, 4 Nov 2025 09:43:38 -0800 Subject: [PATCH 16/17] remove PID file --- test-server/cpp-v2-server/server.pid | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test-server/cpp-v2-server/server.pid diff --git a/test-server/cpp-v2-server/server.pid b/test-server/cpp-v2-server/server.pid deleted file mode 100644 index 7e29010a..00000000 --- a/test-server/cpp-v2-server/server.pid +++ /dev/null @@ -1 +0,0 @@ -45067 From 5c9235f2a9bf52f95a321ff6147b130952eeb536 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Tue, 4 Nov 2025 13:02:05 -0800 Subject: [PATCH 17/17] lint to mac-15 --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 637003f3..bb1655bb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -8,7 +8,7 @@ on: jobs: lint: - runs-on: macos-13 + runs-on: macos-15 steps: - name: Checkout code