From 2f194c13c070b1fc225210f8aea990b6b4facf6b Mon Sep 17 00:00:00 2001 From: texastony <5892063+texastony@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:46:32 -0600 Subject: [PATCH] test(examples): Instruction Files - Add KMS Keyring Instruction File example - Test KMS Keyring Instruction File example - Test ReEncrypt Instruction File examples --- .../s3/examples/InstructionFileExample.java | 92 +++++++++++++++++++ .../examples/InstructionFileExampleTest.java | 21 +++++ .../ReEncryptInstructionFileExampleTest.java | 42 +++++++++ 3 files changed, 155 insertions(+) create mode 100644 src/examples/java/software/amazon/encryption/s3/examples/InstructionFileExample.java create mode 100644 src/test/java/software/amazon/encryption/s3/examples/InstructionFileExampleTest.java create mode 100644 src/test/java/software/amazon/encryption/s3/examples/ReEncryptInstructionFileExampleTest.java diff --git a/src/examples/java/software/amazon/encryption/s3/examples/InstructionFileExample.java b/src/examples/java/software/amazon/encryption/s3/examples/InstructionFileExample.java new file mode 100644 index 000000000..92e9a3564 --- /dev/null +++ b/src/examples/java/software/amazon/encryption/s3/examples/InstructionFileExample.java @@ -0,0 +1,92 @@ +package software.amazon.encryption.s3.examples; + +import java.security.NoSuchAlgorithmException; + +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.kms.KmsClient; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.encryption.s3.S3EncryptionClient; +import software.amazon.encryption.s3.S3EncryptionClientException; +import software.amazon.encryption.s3.internal.InstructionFileConfig; +import software.amazon.encryption.s3.materials.KmsKeyring; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static software.amazon.encryption.s3.utils.S3EncryptionClientTestResources.appendTestSuffix; +import static software.amazon.encryption.s3.utils.S3EncryptionClientTestResources.deleteObject; + +public class InstructionFileExample { + + public static void main(final String[] args) throws NoSuchAlgorithmException { + final String bucket = args[0]; + final String kmsKeyId = args.length > 1 ? args[1] : null; + + if (kmsKeyId != null) { + InstructionFileExample.simpleKmsKeyringUseInstructionFile(bucket, kmsKeyId); + } + } + /** + * This example demonstrates using Instruction Files. + * + * @param bucket The name of the Amazon S3 bucket to perform operations on. + * @param kmsKeyId The KMS key ID used for encryption + */ + public static void simpleKmsKeyringUseInstructionFile( + final String bucket, + final String kmsKeyId + ) { + // Set up the S3 object key and content to be encrypted + final String objectKey = appendTestSuffix( + "kms-instruction-file-test" + ); + final String input = + "Testing encryption of instruction file with KMS Keyring"; + + // Create a KMS client for key operations + KmsClient kmsClient = KmsClient.create(); + + // Create the original KMS keyring with the first KMS key + KmsKeyring originalKeyring = KmsKeyring + .builder() + .kmsClient(kmsClient) + .wrappingKeyId(kmsKeyId) + .build(); + + // Create a default S3 client for instruction file operations + S3Client wrappedClient = S3Client.create(); + + // Create the S3 Encryption Client with instruction file support enabled + // The client can perform both putObject and getObject operations using the KMS key + ResponseBytes decryptedObject; + try (S3EncryptionClient s3ec = S3EncryptionClient + .builderV4() + .keyring(originalKeyring) + .instructionFileConfig( + InstructionFileConfig + .builder() + .instructionFileClient(wrappedClient) + .enableInstructionFilePutObject(true) + .build() + ).build()) { + + // Upload both the encrypted object and instruction file to the specified bucket in S3 + s3ec.putObject( + builder -> builder.bucket(bucket).key(objectKey).build(), + RequestBody.fromString(input) + ); + + // Verify that the client can successfully decrypt the object + decryptedObject = s3ec.getObjectAsBytes(builder -> + builder.bucket(bucket).key(objectKey).build() + ); + // Assert that the decrypted object's content matches the original input + assertEquals(input, decryptedObject.asUtf8String()); + + // Call deleteObject to delete the object and instruction file + // from given S3 Bucket + deleteObject(bucket, objectKey, s3ec); + } + } +} diff --git a/src/test/java/software/amazon/encryption/s3/examples/InstructionFileExampleTest.java b/src/test/java/software/amazon/encryption/s3/examples/InstructionFileExampleTest.java new file mode 100644 index 000000000..22b7543bf --- /dev/null +++ b/src/test/java/software/amazon/encryption/s3/examples/InstructionFileExampleTest.java @@ -0,0 +1,21 @@ +package software.amazon.encryption.s3.examples; + +import org.junit.jupiter.api.Test; +import software.amazon.encryption.s3.utils.S3EncryptionClientTestResources; + +import static org.junit.jupiter.api.Assertions.fail; + +public class InstructionFileExampleTest { + + @Test + public void testInstructionFileExample() { + final String bucket = S3EncryptionClientTestResources.BUCKET; + final String kmsKeyId = S3EncryptionClientTestResources.KMS_KEY_ID; + try { + InstructionFileExample.simpleKmsKeyringUseInstructionFile(bucket, kmsKeyId); + } catch (Throwable exception) { + exception.printStackTrace(); + fail("Instruction File Example Test Failed!!", exception); + } + } +} diff --git a/src/test/java/software/amazon/encryption/s3/examples/ReEncryptInstructionFileExampleTest.java b/src/test/java/software/amazon/encryption/s3/examples/ReEncryptInstructionFileExampleTest.java new file mode 100644 index 000000000..62b677755 --- /dev/null +++ b/src/test/java/software/amazon/encryption/s3/examples/ReEncryptInstructionFileExampleTest.java @@ -0,0 +1,42 @@ +package software.amazon.encryption.s3.examples; + +import org.junit.jupiter.api.Test; +import software.amazon.encryption.s3.utils.S3EncryptionClientTestResources; + +import static org.junit.jupiter.api.Assertions.fail; + +public class ReEncryptInstructionFileExampleTest { + + @Test + public void testSimpleAesKeyringReEncryptInstructionFile() { + final String bucket = S3EncryptionClientTestResources.BUCKET; + try { + ReEncryptInstructionFileExample.simpleAesKeyringReEncryptInstructionFile(bucket); + } catch (Throwable exception) { + exception.printStackTrace(); + fail("AES Keyring ReEncrypt Instruction File Test Failed!!", exception); + } + } + + @Test + public void testSimpleRsaKeyringReEncryptInstructionFile() { + final String bucket = S3EncryptionClientTestResources.BUCKET; + try { + ReEncryptInstructionFileExample.simpleRsaKeyringReEncryptInstructionFile(bucket); + } catch (Throwable exception) { + exception.printStackTrace(); + fail("RSA Keyring ReEncrypt Instruction File Test Failed!!", exception); + } + } + + @Test + public void testSimpleRsaKeyringReEncryptInstructionFileWithCustomSuffix() { + final String bucket = S3EncryptionClientTestResources.BUCKET; + try { + ReEncryptInstructionFileExample.simpleRsaKeyringReEncryptInstructionFileWithCustomSuffix(bucket); + } catch (Throwable exception) { + exception.printStackTrace(); + fail("RSA Keyring ReEncrypt Instruction File With Custom Suffix Test Failed!!", exception); + } + } +}