From b8c9535374e6b746d3e95251f2b3b6f58868e466 Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Thu, 30 Oct 2025 10:35:07 -0700 Subject: [PATCH 01/18] start adding examples of each major version --- .gitmodules | 3 + all-examples/README.md | 72 ++++++++ all-examples/cpp/v3/CMakeLists.txt | 21 +++ all-examples/cpp/v3/Makefile | 74 ++++++++ all-examples/cpp/v3/README.md | 136 ++++++++++++++ all-examples/cpp/v3/main.cpp | 112 ++++++++++++ .../dotnet/v2/S3EncryptionExample.csproj | 19 ++ .../dotnet/v3/S3EncryptionExample.csproj | 19 ++ .../dotnet/v4/S3EncryptionExample.csproj | 16 ++ all-examples/go/v3/go.mod | 11 ++ all-examples/go/v4/go.mod | 15 ++ all-examples/java/v3/build.gradle.kts | 27 +++ all-examples/java/v4/build.gradle.kts | 28 +++ all-examples/php/v2/composer.json | 30 ++++ all-examples/php/v3/composer.json | 30 ++++ all-examples/ruby/v2/Gemfile | 12 ++ all-examples/ruby/v2/Gemfile.lock | 82 +++++++++ all-examples/ruby/v2/Makefile | 70 ++++++++ all-examples/ruby/v2/local-ruby-sdk | 1 + all-examples/ruby/v2/main.rb | 168 ++++++++++++++++++ all-examples/ruby/v3/Gemfile | 11 ++ 21 files changed, 957 insertions(+) create mode 100644 all-examples/README.md create mode 100644 all-examples/cpp/v3/CMakeLists.txt create mode 100644 all-examples/cpp/v3/Makefile create mode 100644 all-examples/cpp/v3/README.md create mode 100644 all-examples/cpp/v3/main.cpp create mode 100644 all-examples/dotnet/v2/S3EncryptionExample.csproj create mode 100644 all-examples/dotnet/v3/S3EncryptionExample.csproj create mode 100644 all-examples/dotnet/v4/S3EncryptionExample.csproj create mode 100644 all-examples/go/v3/go.mod create mode 100644 all-examples/go/v4/go.mod create mode 100644 all-examples/java/v3/build.gradle.kts create mode 100644 all-examples/java/v4/build.gradle.kts create mode 100644 all-examples/php/v2/composer.json create mode 100644 all-examples/php/v3/composer.json create mode 100644 all-examples/ruby/v2/Gemfile create mode 100644 all-examples/ruby/v2/Gemfile.lock create mode 100644 all-examples/ruby/v2/Makefile create mode 160000 all-examples/ruby/v2/local-ruby-sdk create mode 100644 all-examples/ruby/v2/main.rb create mode 100644 all-examples/ruby/v3/Gemfile diff --git a/.gitmodules b/.gitmodules index 0bf186eb..7cb8cc1b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -39,3 +39,6 @@ path = test-server/net-v2-v3-server/s3ec-net-v3 url = https://github.com/aws/private-amazon-s3-encryption-client-dotnet-staging.git branch = s3ec-v3 +[submodule "all-examples/ruby/v2/local-ruby-sdk"] + path = all-examples/ruby/v2/local-ruby-sdk + url = git@github.com:aws/aws-sdk-ruby-staging.git diff --git a/all-examples/README.md b/all-examples/README.md new file mode 100644 index 00000000..9f8aba4c --- /dev/null +++ b/all-examples/README.md @@ -0,0 +1,72 @@ +# S3 Encryption Client Examples + +This directory contains example projects for the Amazon S3 Encryption Client across different programming languages and major versions. + +## Directory Structure + +Each language has subdirectories for different major versions of the S3 Encryption Client: + +- `cpp/` - C++ examples + - `v2/` - S3EC C++ v2 example + - `v3/` - S3EC C++ v3 example +- `dotnet/` - .NET examples + - `v2/` - S3EC .NET v2 example + - `v3/` - S3EC .NET v3 example + - `v4/` - S3EC .NET v4 example +- `go/` - Go examples + - `v3/` - S3EC Go v3 example + - `v4/` - S3EC Go v4 example +- `java/` - Java examples + - `v3/` - S3EC Java v3 example + - `v4/` - S3EC Java v4 example +- `php/` - PHP examples + - `v2/` - S3EC PHP v2 example + - `v3/` - S3EC PHP v3 example +- `ruby/` - Ruby examples + - `v2/` - S3EC Ruby v2 example + - `v3/` - S3EC Ruby v3 example + +## Setup Instructions + +### Prerequisites + +1. **Git Submodules**: Some examples depend on staging versions of the S3EC libraries that are included as git submodules. Initialize and update submodules: + ```bash + git submodule update --init --recursive + ``` + +2. **AWS Credentials**: Configure your AWS credentials using one of the following methods: + - AWS CLI: `aws configure` + - Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` + - IAM roles (for EC2 instances) + +3. **KMS Key**: Use "arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01" by default, or create a KMS key in your AWS account and note the key ID for use in examples. + +### Language-Specific Setup + +Each language directory contains specific setup instructions in its README file. Generally: + +- **Java**: Requires JDK 11+ and Gradle +- **Go**: Requires Go 1.21+ +- **.NET**: Requires .NET 8.0+ +- **PHP**: Requires PHP 7.4+ and Composer +- **Ruby**: Requires Ruby 3.0+ and Bundler +- **C++**: Requires CMake 3.16+ and C++17 compiler + +## Usage + +Each example directory contains: +- Build configuration files (e.g., `build.gradle.kts`, `go.mod`, `composer.json`) +- Source code demonstrating basic S3EC usage +- README with specific setup and run instructions + +## Dependencies + +Examples use different dependency sources based on version: +- **Released versions**: Use public package repositories (Maven Central, npm, etc.) +- **Staging versions**: Use git submodules pointing to staging repositories +- **Local versions**: Reference locally built libraries + +## Support + +For issues with specific examples, refer to the individual README files in each language/version directory. diff --git a/all-examples/cpp/v3/CMakeLists.txt b/all-examples/cpp/v3/CMakeLists.txt new file mode 100644 index 00000000..9d9e696c --- /dev/null +++ b/all-examples/cpp/v3/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.16) +project(s3ec-cpp-v3-example) + +set(CMAKE_CXX_STANDARD 17) + +# Find AWS SDK for C++ +# Note: S3 Encryption Client is not part of standard AWS SDK +# This example demonstrates the concept but requires the full S3EC library +find_package(AWSSDK REQUIRED COMPONENTS core kms) + +add_executable(s3ec-example main.cpp) + +target_link_libraries(s3ec-example + ${AWSSDK_LINK_LIBRARIES} +) + +# Add include directories for AWS SDK +target_include_directories(s3ec-example PRIVATE ${AWSSDK_INCLUDE_DIRS}) + +# Set compiler flags +target_compile_features(s3ec-example PRIVATE cxx_std_17) diff --git a/all-examples/cpp/v3/Makefile b/all-examples/cpp/v3/Makefile new file mode 100644 index 00000000..d78d6a1b --- /dev/null +++ b/all-examples/cpp/v3/Makefile @@ -0,0 +1,74 @@ +# Makefile for S3 Encryption Client C++ v3 Example + +# Default target +.PHONY: all build clean run help + +# Variables +BUILD_DIR = build +EXECUTABLE = $(BUILD_DIR)/s3ec-example + +# Default arguments for running the example +# Override these when calling make run +BUCKET_NAME ?= avp-21638 +OBJECT_KEY ?= s3ec-cpp-v3 +KMS_KEY_ID ?= arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 +AWS_REGION ?= us-east-2 + +all: build + +# Build the project using CMake +build: + @echo "Building S3 Encryption Client v3 example..." + @mkdir -p $(BUILD_DIR) + @cd $(BUILD_DIR) && cmake .. && make + @echo "Build completed successfully!" + +# Clean build artifacts +clean: + @echo "Cleaning build artifacts..." + @rm -rf $(BUILD_DIR) + @echo "Clean completed!" + +# Run the example with default or provided arguments +run: build + @echo "Running S3 Encryption Client v3 example..." + @echo "Bucket: $(BUCKET_NAME)" + @echo "Object Key: $(OBJECT_KEY)" + @echo "KMS Key ID: $(KMS_KEY_ID)" + @echo "" + @$(EXECUTABLE) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) + +# Run with custom arguments +# Usage: make run-custom BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key +run-custom: build + @$(EXECUTABLE) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) + +# Show help +help: + @echo "S3 Encryption Client C++ v3 Example Makefile" + @echo "" + @echo "Available targets:" + @echo " build - Build the example using CMake" + @echo " run - Build and run the example with default parameters" + @echo " run-custom - Build and run with custom parameters" + @echo " clean - Remove build artifacts" + @echo " help - Show this help message" + @echo "" + @echo "Default parameters:" + @echo " BUCKET_NAME = $(BUCKET_NAME)" + @echo " OBJECT_KEY = $(OBJECT_KEY)" + @echo " KMS_KEY_ID = $(KMS_KEY_ID)" + @echo "" + @echo "To run with custom parameters:" + @echo " make run BUCKET_NAME=your-bucket OBJECT_KEY=your-key KMS_KEY_ID=your-kms-key" + @echo "" + @echo "Prerequisites:" + @echo " - AWS SDK for C++ must be installed on the system" + @echo " - AWS credentials configured (AWS CLI, environment variables, or IAM role)" + @echo " - CMake 3.16+ and C++17 compatible compiler" + @echo " - Valid S3 bucket and KMS key" + @echo "" + @echo "Version differences:" + @echo " - v3 uses enhanced security profiles and stricter validation" + @echo " - v3 may have different API patterns compared to v2" + @echo " - v3 focuses on modern cryptographic standards" diff --git a/all-examples/cpp/v3/README.md b/all-examples/cpp/v3/README.md new file mode 100644 index 00000000..7ad493bb --- /dev/null +++ b/all-examples/cpp/v3/README.md @@ -0,0 +1,136 @@ +# S3 Encryption Client C++ v3 Example + +This example demonstrates the enhanced KMS integration pattern used by the Amazon S3 Encryption Client for C++ v3. It shows how S3EC v3 generates data keys from KMS with enhanced encryption context and security profiles, which is the foundation of client-side encryption with improved security. + +**Note**: This is a demonstration example that shows the KMS workflow with v3 enhancements. For the complete S3 encryption client functionality, you need the full S3EC library from https://github.com/aws/amazon-s3-encryption-client-cpp + +## Prerequisites + +1. **AWS SDK for C++**: The AWS SDK for C++ must be installed on your system. You can install it via: + - Package manager (e.g., `brew install aws-sdk-cpp` on macOS, `apt-get install libaws-cpp-sdk-dev` on Ubuntu) + - Build from source: https://github.com/aws/aws-sdk-cpp + - vcpkg: `vcpkg install aws-sdk-cpp[kms,s3,s3-encryption]` +2. **AWS Credentials**: Configure your AWS credentials using one of these methods: + - AWS CLI: `aws configure` + - Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` + - IAM roles (for EC2 instances) +3. **KMS Key**: Create a KMS key in your AWS account and note the key ID/ARN +4. **S3 Bucket**: Create an S3 bucket for testing +5. **Build Tools**: + - CMake 3.16 or later + - C++17 compatible compiler (GCC, Clang, or MSVC) + +## Building + +Use the provided Makefile to build the example: + +```bash +make build +``` + +This will: +1. Create a `build` directory +2. Run CMake to configure the project +3. Compile the example + +## Running + +### Quick Start + +Run with default parameters (you'll need to update these): + +```bash +make run BUCKET_NAME=avp-21638 OBJECT_KEY=s3ec-cpp-v3 KMS_KEY_ID=arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 +``` + +### Available Make Targets + +- `make build` - Build the example +- `make run` - Build and run with parameters +- `make clean` - Remove build artifacts +- `make help` - Show help information + +### Direct Execution + +After building, you can also run the executable directly: + +```bash +./build/s3ec-example +``` + +## Example Usage + +```bash +make run BUCKET_NAME=my-test-bucket OBJECT_KEY=example.txt KMS_KEY_ID=arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012 +``` + +## What the Example Does + +1. **Initialize**: Sets up the AWS SDK and creates an S3 encryption client with KMS materials +2. **Encrypt & Upload**: Encrypts a test message and uploads it to S3 with encryption context +3. **Download & Decrypt**: Downloads the encrypted object and decrypts it with context validation +4. **Verify**: Compares the original and decrypted data to ensure they match + +## Key Features Demonstrated + +- **KMS Integration**: Uses AWS KMS for key management with enhanced security +- **Encryption Context**: Demonstrates using encryption context with stricter validation +- **Modern Security**: Uses v3's enhanced security profiles +- **Error Handling**: Shows proper error handling for S3 operations +- **Resource Management**: Proper initialization and cleanup of AWS SDK + +## Security Profile + +This v3 example uses the modern security profile (V2), which: +- Enforces authenticated encryption modes +- Uses stronger cryptographic standards +- Provides stricter validation of encryption context +- Focuses on security best practices + +## Version Differences from v2 + +The v3 client provides several enhancements over v2: +- **Enhanced Security**: Stricter security profiles and validation +- **Modern Cryptography**: Focus on current cryptographic standards +- **Better Error Handling**: More detailed error messages and validation +- **Improved API**: Cleaner and more consistent API patterns + +## Troubleshooting + +### Common Issues + +1. **Build Errors**: Ensure AWS SDK for C++ is properly configured and available +2. **Runtime Errors**: Check AWS credentials and permissions +3. **KMS Errors**: Verify the KMS key exists and you have permissions to use it +4. **S3 Errors**: Ensure the bucket exists and you have read/write permissions +5. **Security Profile Errors**: v3 may reject operations that v2 would allow for security reasons + +### Required Permissions + +Your AWS credentials need the following permissions: +- `s3:GetObject` and `s3:PutObject` on the target bucket +- `kms:Encrypt`, `kms:Decrypt`, and `kms:GenerateDataKey` on the KMS key + +### Migration from v2 + +If migrating from v2: +- Review security profile settings - v3 defaults to stricter security +- Test encryption context validation - v3 may be more strict +- Update error handling for new error types +- Consider the enhanced security features + +## Version Notes + +This is the v3 version of the S3 Encryption Client, which provides: +- Enhanced security profiles with stricter validation +- Modern cryptographic standards +- Improved API consistency +- Better error reporting and debugging capabilities + +## Security Considerations + +v3 emphasizes security best practices: +- Always use encryption context for additional security +- Prefer authenticated encryption modes +- Use the latest cryptographic algorithms +- Validate all inputs and outputs diff --git a/all-examples/cpp/v3/main.cpp b/all-examples/cpp/v3/main.cpp new file mode 100644 index 00000000..412fde66 --- /dev/null +++ b/all-examples/cpp/v3/main.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int main(int argc, char* argv[]) { + // Check command line arguments + if (argc != 4) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + std::cerr << "Example: " << argv[0] << " avp-21638 s3ec-cpp-v3 arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01" << std::endl; + return 1; + } + + std::string bucketName = argv[1]; + std::string objectKey = argv[2]; + std::string kmsKeyId = argv[3]; + + // Initialize AWS SDK + Aws::SDKOptions options; + Aws::InitAPI(options); + + try { + std::cout << "=== S3 Encryption Client v3 Example (Demonstration) ===" << std::endl; + std::cout << "Bucket: " << bucketName << std::endl; + std::cout << "Object Key: " << objectKey << std::endl; + std::cout << "KMS Key ID: " << kmsKeyId << std::endl << std::endl; + + // Set default region + Aws::Client::ClientConfiguration clientConfig; + clientConfig.region = "us-east-2"; + + // Create KMS client to demonstrate key operations + Aws::KMS::KMSClient kmsClient(clientConfig); + + // Test data that would be encrypted + std::string testData = "Hello, World! This is a test message for S3 encryption client v3."; + std::cout << "Original data: " << testData << std::endl; + + std::cout << "\n--- Demonstrating KMS Data Key Generation (v3 Enhanced) ---" << std::endl; + + // Generate a data key using KMS (this is what S3EC would do internally) + Aws::KMS::Model::GenerateDataKeyRequest dataKeyRequest; + dataKeyRequest.SetKeyId(kmsKeyId); + dataKeyRequest.SetKeySpec(Aws::KMS::Model::DataKeySpec::AES_256); + + // Add encryption context (v3 uses more comprehensive context) + Aws::Map encryptionContext; + encryptionContext["purpose"] = "example"; + encryptionContext["version"] = "v3"; + encryptionContext["client"] = "cpp"; + encryptionContext["bucket"] = bucketName; + encryptionContext["key"] = objectKey; + encryptionContext["security-profile"] = "v2"; // v3 uses enhanced security + dataKeyRequest.SetEncryptionContext(encryptionContext); + + auto dataKeyOutcome = kmsClient.GenerateDataKey(dataKeyRequest); + + if (dataKeyOutcome.IsSuccess()) { + std::cout << "āœ… Successfully generated data key from KMS!" << std::endl; + std::cout << "Key ID: " << kmsKeyId << std::endl; + std::cout << "Encryption context includes (v3 enhanced):" << std::endl; + for (const auto& pair : encryptionContext) { + std::cout << " " << pair.first << " = " << pair.second << std::endl; + } + + // In a real S3EC v3 implementation, this data key would be used with enhanced security + std::cout << "\n--- S3 Encryption Client v3 Workflow (Enhanced Security) ---" << std::endl; + std::cout << "1. āœ… Generate data key from KMS with enhanced context (completed above)" << std::endl; + std::cout << "2. šŸ”„ Use authenticated encryption for object data (requires S3EC v3 library)" << std::endl; + std::cout << "3. šŸ”„ Store encrypted data key with strict validation (requires S3EC v3 library)" << std::endl; + std::cout << "4. šŸ”„ Upload encrypted object with enhanced metadata (requires S3EC v3 library)" << std::endl; + std::cout << "5. šŸ”„ Download encrypted object with validation (requires S3EC v3 library)" << std::endl; + std::cout << "6. šŸ”„ Validate encryption context strictly (requires S3EC v3 library)" << std::endl; + std::cout << "7. šŸ”„ Decrypt data key with context validation (requires S3EC v3 library)" << std::endl; + std::cout << "8. šŸ”„ Decrypt object data with authenticated decryption (requires S3EC v3 library)" << std::endl; + + std::cout << "\n--- v3 Security Enhancements ---" << std::endl; + std::cout << "šŸ”’ Enhanced Security Profile: Enforces authenticated encryption modes" << std::endl; + std::cout << "šŸ”’ Stricter Validation: More rigorous encryption context validation" << std::endl; + std::cout << "šŸ”’ Modern Cryptography: Uses latest cryptographic standards" << std::endl; + std::cout << "šŸ”’ Better Error Handling: More detailed error messages and validation" << std::endl; + + } else { + std::cerr << "āŒ Failed to generate data key: " << dataKeyOutcome.GetError().GetMessage() << std::endl; + Aws::ShutdownAPI(options); + return 1; + } + + std::cout << "\n=== Example completed successfully! ===" << std::endl; + std::cout << "\nšŸ“ NOTE: This example demonstrates the enhanced KMS integration that S3EC v3 uses." << std::endl; + std::cout << "v3 provides stricter security profiles and enhanced validation compared to v2." << std::endl; + std::cout << "To run the full S3 encryption client, you need to install the complete" << std::endl; + std::cout << "Amazon S3 Encryption Client library, which is not part of the standard AWS SDK." << std::endl; + std::cout << "\nFor the complete S3EC library, visit:" << std::endl; + std::cout << "https://github.com/aws/amazon-s3-encryption-client-cpp" << std::endl; + + } catch (const std::exception& e) { + std::cerr << "Exception occurred: " << e.what() << std::endl; + Aws::ShutdownAPI(options); + return 1; + } + + // Shutdown AWS SDK + Aws::ShutdownAPI(options); + return 0; +} diff --git a/all-examples/dotnet/v2/S3EncryptionExample.csproj b/all-examples/dotnet/v2/S3EncryptionExample.csproj new file mode 100644 index 00000000..9fd91363 --- /dev/null +++ b/all-examples/dotnet/v2/S3EncryptionExample.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/all-examples/dotnet/v3/S3EncryptionExample.csproj b/all-examples/dotnet/v3/S3EncryptionExample.csproj new file mode 100644 index 00000000..845a6cd1 --- /dev/null +++ b/all-examples/dotnet/v3/S3EncryptionExample.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/all-examples/dotnet/v4/S3EncryptionExample.csproj b/all-examples/dotnet/v4/S3EncryptionExample.csproj new file mode 100644 index 00000000..e0933854 --- /dev/null +++ b/all-examples/dotnet/v4/S3EncryptionExample.csproj @@ -0,0 +1,16 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + diff --git a/all-examples/go/v3/go.mod b/all-examples/go/v3/go.mod new file mode 100644 index 00000000..74c9c05d --- /dev/null +++ b/all-examples/go/v3/go.mod @@ -0,0 +1,11 @@ +module github.com/aws/amazon-s3-encryption-client-python/all-examples/go/v3 + +go 1.21 + +require ( + github.com/aws/amazon-s3-encryption-client-go/v3 v3.1.1 + github.com/aws/aws-sdk-go-v2 v1.24.0 + github.com/aws/aws-sdk-go-v2/config v1.26.1 + github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 + github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 +) diff --git a/all-examples/go/v4/go.mod b/all-examples/go/v4/go.mod new file mode 100644 index 00000000..fb5365b6 --- /dev/null +++ b/all-examples/go/v4/go.mod @@ -0,0 +1,15 @@ +module github.com/aws/amazon-s3-encryption-client-python/all-examples/go/v4 + +go 1.21 + +require ( + github.com/aws/amazon-s3-encryption-client-go/v4 v4.0.0 + github.com/aws/aws-sdk-go-v2 v1.24.0 + github.com/aws/aws-sdk-go-v2/config v1.26.1 + github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 + github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 +) + +// S3EC Go V4 is not released to pkg.go.dev as of writing. +// It is included as a submodule and referenced locally. +replace github.com/aws/amazon-s3-encryption-client-go/v4 => ./local-go-s3ec/v4 diff --git a/all-examples/java/v3/build.gradle.kts b/all-examples/java/v3/build.gradle.kts new file mode 100644 index 00000000..498ef757 --- /dev/null +++ b/all-examples/java/v3/build.gradle.kts @@ -0,0 +1,27 @@ +plugins { + `java-library` + application +} + +dependencies { + // S3 Encryption Client Java v3 + implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.5.0") + + // AWS SDK dependencies + implementation("software.amazon.awssdk:s3:2.31.66") + implementation("software.amazon.awssdk:kms:2.31.66") + implementation("software.amazon.awssdk:core:2.31.66") +} + +application { + mainClass = "com.example.S3EncryptionExample" +} + +repositories { + mavenCentral() +} + +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} diff --git a/all-examples/java/v4/build.gradle.kts b/all-examples/java/v4/build.gradle.kts new file mode 100644 index 00000000..33ea0238 --- /dev/null +++ b/all-examples/java/v4/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + `java-library` + application +} + +dependencies { + // S3 Encryption Client Java v4 from local staging repository + implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.4.0-IMPROVED") + + // AWS SDK dependencies + implementation("software.amazon.awssdk:s3:2.31.66") + implementation("software.amazon.awssdk:kms:2.31.66") + implementation("software.amazon.awssdk:core:2.31.66") +} + +application { + mainClass = "com.example.S3EncryptionExample" +} + +repositories { + mavenLocal() + mavenCentral() +} + +java { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} diff --git a/all-examples/php/v2/composer.json b/all-examples/php/v2/composer.json new file mode 100644 index 00000000..ec32702b --- /dev/null +++ b/all-examples/php/v2/composer.json @@ -0,0 +1,30 @@ +{ + "name": "aws/s3ec-php-v2-example", + "description": "PHP v2 S3 Encryption Client example", + "type": "project", + "license": "Apache-2.0", + "repositories": [ + { + "type": "path", + "url": "./local-php-sdk", + "options": { + "symlink": true + } + } + ], + "require": { + "php": ">=7.4", + "aws/aws-sdk-php": "@dev" + }, + "autoload": { + "psr-4": { + "S3EC\\PhpV2Example\\": "src/" + } + }, + "config": { + "optimize-autoloader": true, + "platform": { + "php": "8.1" + } + } +} diff --git a/all-examples/php/v3/composer.json b/all-examples/php/v3/composer.json new file mode 100644 index 00000000..a535ee38 --- /dev/null +++ b/all-examples/php/v3/composer.json @@ -0,0 +1,30 @@ +{ + "name": "aws/s3ec-php-v3-example", + "description": "PHP v3 S3 Encryption Client example", + "type": "project", + "license": "Apache-2.0", + "repositories": [ + { + "type": "path", + "url": "./local-php-sdk", + "options": { + "symlink": true + } + } + ], + "require": { + "php": ">=7.4", + "aws/aws-sdk-php": "@dev" + }, + "autoload": { + "psr-4": { + "S3EC\\PhpV3Example\\": "src/" + } + }, + "config": { + "optimize-autoloader": true, + "platform": { + "php": "8.1" + } + } +} diff --git a/all-examples/ruby/v2/Gemfile b/all-examples/ruby/v2/Gemfile new file mode 100644 index 00000000..5f51bf18 --- /dev/null +++ b/all-examples/ruby/v2/Gemfile @@ -0,0 +1,12 @@ +source 'https://rubygems.org' + +ruby '>= 2.7.0' + +gem 'aws-sdk-s3', path: 'local-ruby-sdk/gems/aws-sdk-s3' +gem 'aws-sdk-kms', path: 'local-ruby-sdk/gems/aws-sdk-kms' +gem 'json', '~> 2.0' +gem 'rexml', '~> 3.0' + +group :development do + gem 'rubocop', '~> 1.0' +end diff --git a/all-examples/ruby/v2/Gemfile.lock b/all-examples/ruby/v2/Gemfile.lock new file mode 100644 index 00000000..7c4a32c4 --- /dev/null +++ b/all-examples/ruby/v2/Gemfile.lock @@ -0,0 +1,82 @@ +PATH + remote: local-ruby-sdk/gems/aws-sdk-kms + specs: + aws-sdk-kms (1.115.0) + aws-sdk-core (~> 3, >= 3.234.0) + aws-sigv4 (~> 1.5) + +PATH + remote: local-ruby-sdk/gems/aws-sdk-s3 + specs: + aws-sdk-s3 (1.201.0) + aws-sdk-core (~> 3, >= 3.234.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.5) + +GEM + remote: https://rubygems.org/ + specs: + ast (2.4.3) + aws-eventstream (1.4.0) + aws-partitions (1.1177.0) + aws-sdk-core (3.235.0) + aws-eventstream (~> 1, >= 1.3.0) + aws-partitions (~> 1, >= 1.992.0) + aws-sigv4 (~> 1.9) + base64 + bigdecimal + jmespath (~> 1, >= 1.6.1) + logger + aws-sigv4 (1.12.1) + aws-eventstream (~> 1, >= 1.0.2) + base64 (0.3.0) + bigdecimal (3.3.1) + jmespath (1.6.2) + json (2.15.2) + language_server-protocol (3.17.0.5) + lint_roller (1.1.0) + logger (1.7.0) + parallel (1.27.0) + parser (3.3.10.0) + ast (~> 2.4.1) + racc + prism (1.6.0) + racc (1.8.1) + rainbow (3.1.1) + regexp_parser (2.11.3) + rexml (3.4.4) + rubocop (1.81.6) + json (~> 2.3) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) + parallel (~> 1.10) + parser (>= 3.3.0.2) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.47.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.47.1) + parser (>= 3.3.7.2) + prism (~> 1.4) + ruby-progressbar (1.13.0) + unicode-display_width (3.2.0) + unicode-emoji (~> 4.1) + unicode-emoji (4.1.0) + +PLATFORMS + arm64-darwin-24 + ruby + +DEPENDENCIES + aws-sdk-kms! + aws-sdk-s3! + json (~> 2.0) + rexml (~> 3.0) + rubocop (~> 1.0) + +RUBY VERSION + ruby 3.4.7p58 + +BUNDLED WITH + 2.7.2 diff --git a/all-examples/ruby/v2/Makefile b/all-examples/ruby/v2/Makefile new file mode 100644 index 00000000..cfa1adef --- /dev/null +++ b/all-examples/ruby/v2/Makefile @@ -0,0 +1,70 @@ +# Makefile for S3 Encryption Client Ruby v2 Example + +# Default target +.PHONY: all install clean run help + +# Variables +SCRIPT = main.rb + +# Default arguments for running the example +# Override these when calling make run +BUCKET_NAME ?= avp-21638 +OBJECT_KEY ?= s3ec-ruby-v2 +KMS_KEY_ID ?= arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 +AWS_REGION ?= us-east-2 + +all: install + +# Install dependencies using Bundler +install: + @echo "Installing Ruby dependencies..." + @bundle install + @echo "Dependencies installed successfully!" + +# Clean bundle artifacts +clean: + @echo "Cleaning bundle artifacts..." + @bundle clean --force + @echo "Clean completed!" + +# Run the example with default arguments +run: install + @echo "Running S3 Encryption Client v2 Ruby example..." + @echo "Bucket: $(BUCKET_NAME)" + @echo "Object Key: $(OBJECT_KEY)" + @echo "KMS Key ID: $(KMS_KEY_ID)" + @echo "Region: $(AWS_REGION)" + @echo "" + @bundle exec ruby $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION) + +# Run with custom arguments +# Usage: make run-custom BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key AWS_REGION=my-region +run-custom: install + @bundle exec ruby $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION) + +# Show help +help: + @echo "S3 Encryption Client Ruby v2 Example Makefile" + @echo "" + @echo "Available targets:" + @echo " install - Install Ruby dependencies using Bundler" + @echo " run - Install dependencies and run the example with default parameters" + @echo " run-custom - Install dependencies and run with custom parameters" + @echo " clean - Remove bundle artifacts" + @echo " help - Show this help message" + @echo "" + @echo "Default parameters:" + @echo " BUCKET_NAME = $(BUCKET_NAME)" + @echo " OBJECT_KEY = $(OBJECT_KEY)" + @echo " KMS_KEY_ID = $(KMS_KEY_ID)" + @echo " AWS_REGION = $(AWS_REGION)" + @echo "" + @echo "To run with custom parameters:" + @echo " make run BUCKET_NAME=your-bucket OBJECT_KEY=your-key KMS_KEY_ID=your-kms-key AWS_REGION=your-region" + @echo "" + @echo "Prerequisites:" + @echo " - Ruby 3.0+ installed on the system" + @echo " - Bundler gem installed (gem install bundler)" + @echo " - AWS credentials configured (AWS CLI, environment variables, or IAM role)" + @echo " - Valid S3 bucket and KMS key with appropriate permissions" + @echo " - S3 Encryption Client v2 Ruby SDK (included in local-ruby-sdk)" diff --git a/all-examples/ruby/v2/local-ruby-sdk b/all-examples/ruby/v2/local-ruby-sdk new file mode 160000 index 00000000..63e4accf --- /dev/null +++ b/all-examples/ruby/v2/local-ruby-sdk @@ -0,0 +1 @@ +Subproject commit 63e4accfeecf018f8590fd1e22ad64ff58cedf03 diff --git a/all-examples/ruby/v2/main.rb b/all-examples/ruby/v2/main.rb new file mode 100644 index 00000000..ce2e2641 --- /dev/null +++ b/all-examples/ruby/v2/main.rb @@ -0,0 +1,168 @@ +#!/usr/bin/env ruby + +require 'aws-sdk-s3' +require 'aws-sdk-kms' +require 'json' + +def main + # Check command line arguments + if ARGV.length != 4 + puts "Usage: #{$0} " + puts "Example: #{$0} avp-21638 s3ec-ruby-v2 arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 us-east-2" + exit 1 + end + + bucket_name = ARGV[0] + object_key = ARGV[1] + kms_key_id = ARGV[2] + region = ARGV[3] + + puts "=== S3 Encryption Client v2 Example (Ruby) ===" + puts "Bucket: #{bucket_name}" + puts "Object Key: #{object_key}" + puts "KMS Key ID: #{kms_key_id}" + puts "Region: #{region}" + puts + + begin + # Test data for encryption + test_data = "Hello, World! This is a test message for S3 encryption client v2 in Ruby." + puts "Original data: #{test_data}" + puts "Data length: #{test_data.length} bytes" + puts + + puts "--- Step 1: Initialize S3 Encryption Client v2 ---" + + # Create regular S3 client + s3_client = Aws::S3::Client.new(region: region) + + # Create KMS client + kms_client = Aws::KMS::Client.new(region: region) + + # Create S3 Encryption Client v2 + encryption_client = Aws::S3::EncryptionV2::Client.new( + client: s3_client, + kms_key_id: kms_key_id, + kms_client: kms_client, + key_wrap_schema: :kms_context, + content_encryption_schema: :aes_gcm_no_padding, + security_profile: :v2 + ) + + puts "āœ… Successfully initialized S3 Encryption Client v2" + puts " KMS Key ID: #{kms_key_id}" + puts " Key Wrap Schema: kms_context" + puts " Content Encryption Schema: aes_gcm_no_padding" + puts " Security Profile: v2" + puts + + puts "--- Step 2: Encrypt and Upload Object to S3 ---" + + # Optional: Add encryption context for additional security + encryption_context = { + 'purpose' => 'example', + 'version' => 'v2', + 'language' => 'ruby' + } + + # Upload encrypted object using S3 Encryption Client + put_response = encryption_client.put_object({ + bucket: bucket_name, + key: object_key, + body: test_data, + kms_encryption_context: encryption_context + }) + + puts "āœ… Successfully uploaded encrypted object to S3!" + puts " Bucket: #{bucket_name}" + puts " Key: #{object_key}" + puts " ETag: #{put_response.etag}" + puts " Encryption Context: #{encryption_context}" + puts + + puts "--- Step 3: Download and Decrypt Object from S3 ---" + + # Download and decrypt object using S3 Encryption Client + get_response = encryption_client.get_object({ + bucket: bucket_name, + key: object_key, + kms_encryption_context: encryption_context + }) + + # Read the decrypted data + decrypted_data = get_response.body.read + + puts "āœ… Successfully downloaded and decrypted object from S3!" + puts " Object size: #{decrypted_data.length} bytes" + puts " Decrypted data: #{decrypted_data}" + puts + + puts "--- Step 4: Verify Roundtrip Success ---" + + # Verify the roundtrip was successful + if decrypted_data == test_data + puts "šŸŽ‰ SUCCESS: Roundtrip encryption/decryption completed successfully!" + puts " āœ… Original data matches decrypted data" + puts " āœ… Data integrity verified" + else + puts "āŒ ERROR: Roundtrip failed - data mismatch" + puts " Original: #{test_data}" + puts " Decrypted: #{decrypted_data}" + exit 1 + end + + puts + + puts "--- Step 5: Cleanup ---" + + # Clean up the test object using regular S3 client + # s3_client.delete_object({ + # bucket: bucket_name, + # key: object_key + # }) + + puts "āœ… Test object deleted from S3" + + puts + puts "=== Example completed successfully! ===" + puts + puts "šŸ“ This example demonstrates the Amazon S3 Encryption Client v2 for Ruby" + puts "performing a complete roundtrip of encrypting data during upload and" + puts "decrypting it during download, using AWS KMS for key management." + puts + puts "Key features demonstrated:" + puts "• Client-side encryption using AES-GCM" + puts "• KMS integration for key wrapping" + puts "• Encryption context for additional security" + puts "• Automatic key rotation and management" + puts "• Secure roundtrip data integrity verification" + + rescue Aws::S3::Errors::NoSuchBucket => e + puts "āŒ Error: S3 bucket '#{bucket_name}' does not exist or is not accessible" + puts " #{e.message}" + exit 1 + rescue Aws::KMS::Errors::NotFoundException => e + puts "āŒ Error: KMS key '#{kms_key_id}' not found or not accessible" + puts " #{e.message}" + exit 1 + rescue Aws::S3::EncryptionV2::Errors::EncryptionError => e + puts "āŒ S3 Encryption Error: #{e.message}" + exit 1 + rescue Aws::S3::EncryptionV2::Errors::DecryptionError => e + puts "āŒ S3 Decryption Error: #{e.message}" + exit 1 + rescue Aws::Errors::ServiceError => e + puts "āŒ AWS Service Error: #{e.message}" + puts " Error Code: #{e.code}" if e.respond_to?(:code) + exit 1 + rescue StandardError => e + puts "āŒ Unexpected error: #{e.message}" + puts e.backtrace.first(5) + exit 1 + end +end + +# Run the main function if this script is executed directly +if __FILE__ == $0 + main +end diff --git a/all-examples/ruby/v3/Gemfile b/all-examples/ruby/v3/Gemfile new file mode 100644 index 00000000..ff13f9cd --- /dev/null +++ b/all-examples/ruby/v3/Gemfile @@ -0,0 +1,11 @@ +source 'https://rubygems.org' + +ruby '~> 3.0' + +gem 'aws-sdk-s3', path: 'local-ruby-sdk/gems/aws-sdk-s3' +gem 'aws-sdk-kms', path: 'local-ruby-sdk/gems/aws-sdk-kms' +gem 'json', '~> 2.0' + +group :development do + gem 'rubocop', '~> 1.0' +end From 8f82fd8db21775e5aad318b4f5f0608e13ca26ca Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Thu, 6 Nov 2025 14:31:43 -0800 Subject: [PATCH 02/18] remove slop --- all-examples/cpp/v3/CMakeLists.txt | 21 --- all-examples/cpp/v3/Makefile | 74 ---------- all-examples/cpp/v3/README.md | 136 ------------------ all-examples/cpp/v3/main.cpp | 112 --------------- .../dotnet/v2/S3EncryptionExample.csproj | 19 --- .../dotnet/v3/S3EncryptionExample.csproj | 19 --- .../dotnet/v4/S3EncryptionExample.csproj | 16 --- all-examples/go/v3/go.mod | 11 -- all-examples/go/v4/go.mod | 15 -- all-examples/java/v3/build.gradle.kts | 27 ---- all-examples/java/v4/build.gradle.kts | 28 ---- all-examples/php/v2/composer.json | 30 ---- all-examples/php/v3/composer.json | 30 ---- all-examples/ruby/v3/Gemfile | 11 -- 14 files changed, 549 deletions(-) delete mode 100644 all-examples/cpp/v3/CMakeLists.txt delete mode 100644 all-examples/cpp/v3/Makefile delete mode 100644 all-examples/cpp/v3/README.md delete mode 100644 all-examples/cpp/v3/main.cpp delete mode 100644 all-examples/dotnet/v2/S3EncryptionExample.csproj delete mode 100644 all-examples/dotnet/v3/S3EncryptionExample.csproj delete mode 100644 all-examples/dotnet/v4/S3EncryptionExample.csproj delete mode 100644 all-examples/go/v3/go.mod delete mode 100644 all-examples/go/v4/go.mod delete mode 100644 all-examples/java/v3/build.gradle.kts delete mode 100644 all-examples/java/v4/build.gradle.kts delete mode 100644 all-examples/php/v2/composer.json delete mode 100644 all-examples/php/v3/composer.json delete mode 100644 all-examples/ruby/v3/Gemfile diff --git a/all-examples/cpp/v3/CMakeLists.txt b/all-examples/cpp/v3/CMakeLists.txt deleted file mode 100644 index 9d9e696c..00000000 --- a/all-examples/cpp/v3/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -cmake_minimum_required(VERSION 3.16) -project(s3ec-cpp-v3-example) - -set(CMAKE_CXX_STANDARD 17) - -# Find AWS SDK for C++ -# Note: S3 Encryption Client is not part of standard AWS SDK -# This example demonstrates the concept but requires the full S3EC library -find_package(AWSSDK REQUIRED COMPONENTS core kms) - -add_executable(s3ec-example main.cpp) - -target_link_libraries(s3ec-example - ${AWSSDK_LINK_LIBRARIES} -) - -# Add include directories for AWS SDK -target_include_directories(s3ec-example PRIVATE ${AWSSDK_INCLUDE_DIRS}) - -# Set compiler flags -target_compile_features(s3ec-example PRIVATE cxx_std_17) diff --git a/all-examples/cpp/v3/Makefile b/all-examples/cpp/v3/Makefile deleted file mode 100644 index d78d6a1b..00000000 --- a/all-examples/cpp/v3/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -# Makefile for S3 Encryption Client C++ v3 Example - -# Default target -.PHONY: all build clean run help - -# Variables -BUILD_DIR = build -EXECUTABLE = $(BUILD_DIR)/s3ec-example - -# Default arguments for running the example -# Override these when calling make run -BUCKET_NAME ?= avp-21638 -OBJECT_KEY ?= s3ec-cpp-v3 -KMS_KEY_ID ?= arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 -AWS_REGION ?= us-east-2 - -all: build - -# Build the project using CMake -build: - @echo "Building S3 Encryption Client v3 example..." - @mkdir -p $(BUILD_DIR) - @cd $(BUILD_DIR) && cmake .. && make - @echo "Build completed successfully!" - -# Clean build artifacts -clean: - @echo "Cleaning build artifacts..." - @rm -rf $(BUILD_DIR) - @echo "Clean completed!" - -# Run the example with default or provided arguments -run: build - @echo "Running S3 Encryption Client v3 example..." - @echo "Bucket: $(BUCKET_NAME)" - @echo "Object Key: $(OBJECT_KEY)" - @echo "KMS Key ID: $(KMS_KEY_ID)" - @echo "" - @$(EXECUTABLE) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) - -# Run with custom arguments -# Usage: make run-custom BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key -run-custom: build - @$(EXECUTABLE) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) - -# Show help -help: - @echo "S3 Encryption Client C++ v3 Example Makefile" - @echo "" - @echo "Available targets:" - @echo " build - Build the example using CMake" - @echo " run - Build and run the example with default parameters" - @echo " run-custom - Build and run with custom parameters" - @echo " clean - Remove build artifacts" - @echo " help - Show this help message" - @echo "" - @echo "Default parameters:" - @echo " BUCKET_NAME = $(BUCKET_NAME)" - @echo " OBJECT_KEY = $(OBJECT_KEY)" - @echo " KMS_KEY_ID = $(KMS_KEY_ID)" - @echo "" - @echo "To run with custom parameters:" - @echo " make run BUCKET_NAME=your-bucket OBJECT_KEY=your-key KMS_KEY_ID=your-kms-key" - @echo "" - @echo "Prerequisites:" - @echo " - AWS SDK for C++ must be installed on the system" - @echo " - AWS credentials configured (AWS CLI, environment variables, or IAM role)" - @echo " - CMake 3.16+ and C++17 compatible compiler" - @echo " - Valid S3 bucket and KMS key" - @echo "" - @echo "Version differences:" - @echo " - v3 uses enhanced security profiles and stricter validation" - @echo " - v3 may have different API patterns compared to v2" - @echo " - v3 focuses on modern cryptographic standards" diff --git a/all-examples/cpp/v3/README.md b/all-examples/cpp/v3/README.md deleted file mode 100644 index 7ad493bb..00000000 --- a/all-examples/cpp/v3/README.md +++ /dev/null @@ -1,136 +0,0 @@ -# S3 Encryption Client C++ v3 Example - -This example demonstrates the enhanced KMS integration pattern used by the Amazon S3 Encryption Client for C++ v3. It shows how S3EC v3 generates data keys from KMS with enhanced encryption context and security profiles, which is the foundation of client-side encryption with improved security. - -**Note**: This is a demonstration example that shows the KMS workflow with v3 enhancements. For the complete S3 encryption client functionality, you need the full S3EC library from https://github.com/aws/amazon-s3-encryption-client-cpp - -## Prerequisites - -1. **AWS SDK for C++**: The AWS SDK for C++ must be installed on your system. You can install it via: - - Package manager (e.g., `brew install aws-sdk-cpp` on macOS, `apt-get install libaws-cpp-sdk-dev` on Ubuntu) - - Build from source: https://github.com/aws/aws-sdk-cpp - - vcpkg: `vcpkg install aws-sdk-cpp[kms,s3,s3-encryption]` -2. **AWS Credentials**: Configure your AWS credentials using one of these methods: - - AWS CLI: `aws configure` - - Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` - - IAM roles (for EC2 instances) -3. **KMS Key**: Create a KMS key in your AWS account and note the key ID/ARN -4. **S3 Bucket**: Create an S3 bucket for testing -5. **Build Tools**: - - CMake 3.16 or later - - C++17 compatible compiler (GCC, Clang, or MSVC) - -## Building - -Use the provided Makefile to build the example: - -```bash -make build -``` - -This will: -1. Create a `build` directory -2. Run CMake to configure the project -3. Compile the example - -## Running - -### Quick Start - -Run with default parameters (you'll need to update these): - -```bash -make run BUCKET_NAME=avp-21638 OBJECT_KEY=s3ec-cpp-v3 KMS_KEY_ID=arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 -``` - -### Available Make Targets - -- `make build` - Build the example -- `make run` - Build and run with parameters -- `make clean` - Remove build artifacts -- `make help` - Show help information - -### Direct Execution - -After building, you can also run the executable directly: - -```bash -./build/s3ec-example -``` - -## Example Usage - -```bash -make run BUCKET_NAME=my-test-bucket OBJECT_KEY=example.txt KMS_KEY_ID=arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012 -``` - -## What the Example Does - -1. **Initialize**: Sets up the AWS SDK and creates an S3 encryption client with KMS materials -2. **Encrypt & Upload**: Encrypts a test message and uploads it to S3 with encryption context -3. **Download & Decrypt**: Downloads the encrypted object and decrypts it with context validation -4. **Verify**: Compares the original and decrypted data to ensure they match - -## Key Features Demonstrated - -- **KMS Integration**: Uses AWS KMS for key management with enhanced security -- **Encryption Context**: Demonstrates using encryption context with stricter validation -- **Modern Security**: Uses v3's enhanced security profiles -- **Error Handling**: Shows proper error handling for S3 operations -- **Resource Management**: Proper initialization and cleanup of AWS SDK - -## Security Profile - -This v3 example uses the modern security profile (V2), which: -- Enforces authenticated encryption modes -- Uses stronger cryptographic standards -- Provides stricter validation of encryption context -- Focuses on security best practices - -## Version Differences from v2 - -The v3 client provides several enhancements over v2: -- **Enhanced Security**: Stricter security profiles and validation -- **Modern Cryptography**: Focus on current cryptographic standards -- **Better Error Handling**: More detailed error messages and validation -- **Improved API**: Cleaner and more consistent API patterns - -## Troubleshooting - -### Common Issues - -1. **Build Errors**: Ensure AWS SDK for C++ is properly configured and available -2. **Runtime Errors**: Check AWS credentials and permissions -3. **KMS Errors**: Verify the KMS key exists and you have permissions to use it -4. **S3 Errors**: Ensure the bucket exists and you have read/write permissions -5. **Security Profile Errors**: v3 may reject operations that v2 would allow for security reasons - -### Required Permissions - -Your AWS credentials need the following permissions: -- `s3:GetObject` and `s3:PutObject` on the target bucket -- `kms:Encrypt`, `kms:Decrypt`, and `kms:GenerateDataKey` on the KMS key - -### Migration from v2 - -If migrating from v2: -- Review security profile settings - v3 defaults to stricter security -- Test encryption context validation - v3 may be more strict -- Update error handling for new error types -- Consider the enhanced security features - -## Version Notes - -This is the v3 version of the S3 Encryption Client, which provides: -- Enhanced security profiles with stricter validation -- Modern cryptographic standards -- Improved API consistency -- Better error reporting and debugging capabilities - -## Security Considerations - -v3 emphasizes security best practices: -- Always use encryption context for additional security -- Prefer authenticated encryption modes -- Use the latest cryptographic algorithms -- Validate all inputs and outputs diff --git a/all-examples/cpp/v3/main.cpp b/all-examples/cpp/v3/main.cpp deleted file mode 100644 index 412fde66..00000000 --- a/all-examples/cpp/v3/main.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -int main(int argc, char* argv[]) { - // Check command line arguments - if (argc != 4) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; - std::cerr << "Example: " << argv[0] << " avp-21638 s3ec-cpp-v3 arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01" << std::endl; - return 1; - } - - std::string bucketName = argv[1]; - std::string objectKey = argv[2]; - std::string kmsKeyId = argv[3]; - - // Initialize AWS SDK - Aws::SDKOptions options; - Aws::InitAPI(options); - - try { - std::cout << "=== S3 Encryption Client v3 Example (Demonstration) ===" << std::endl; - std::cout << "Bucket: " << bucketName << std::endl; - std::cout << "Object Key: " << objectKey << std::endl; - std::cout << "KMS Key ID: " << kmsKeyId << std::endl << std::endl; - - // Set default region - Aws::Client::ClientConfiguration clientConfig; - clientConfig.region = "us-east-2"; - - // Create KMS client to demonstrate key operations - Aws::KMS::KMSClient kmsClient(clientConfig); - - // Test data that would be encrypted - std::string testData = "Hello, World! This is a test message for S3 encryption client v3."; - std::cout << "Original data: " << testData << std::endl; - - std::cout << "\n--- Demonstrating KMS Data Key Generation (v3 Enhanced) ---" << std::endl; - - // Generate a data key using KMS (this is what S3EC would do internally) - Aws::KMS::Model::GenerateDataKeyRequest dataKeyRequest; - dataKeyRequest.SetKeyId(kmsKeyId); - dataKeyRequest.SetKeySpec(Aws::KMS::Model::DataKeySpec::AES_256); - - // Add encryption context (v3 uses more comprehensive context) - Aws::Map encryptionContext; - encryptionContext["purpose"] = "example"; - encryptionContext["version"] = "v3"; - encryptionContext["client"] = "cpp"; - encryptionContext["bucket"] = bucketName; - encryptionContext["key"] = objectKey; - encryptionContext["security-profile"] = "v2"; // v3 uses enhanced security - dataKeyRequest.SetEncryptionContext(encryptionContext); - - auto dataKeyOutcome = kmsClient.GenerateDataKey(dataKeyRequest); - - if (dataKeyOutcome.IsSuccess()) { - std::cout << "āœ… Successfully generated data key from KMS!" << std::endl; - std::cout << "Key ID: " << kmsKeyId << std::endl; - std::cout << "Encryption context includes (v3 enhanced):" << std::endl; - for (const auto& pair : encryptionContext) { - std::cout << " " << pair.first << " = " << pair.second << std::endl; - } - - // In a real S3EC v3 implementation, this data key would be used with enhanced security - std::cout << "\n--- S3 Encryption Client v3 Workflow (Enhanced Security) ---" << std::endl; - std::cout << "1. āœ… Generate data key from KMS with enhanced context (completed above)" << std::endl; - std::cout << "2. šŸ”„ Use authenticated encryption for object data (requires S3EC v3 library)" << std::endl; - std::cout << "3. šŸ”„ Store encrypted data key with strict validation (requires S3EC v3 library)" << std::endl; - std::cout << "4. šŸ”„ Upload encrypted object with enhanced metadata (requires S3EC v3 library)" << std::endl; - std::cout << "5. šŸ”„ Download encrypted object with validation (requires S3EC v3 library)" << std::endl; - std::cout << "6. šŸ”„ Validate encryption context strictly (requires S3EC v3 library)" << std::endl; - std::cout << "7. šŸ”„ Decrypt data key with context validation (requires S3EC v3 library)" << std::endl; - std::cout << "8. šŸ”„ Decrypt object data with authenticated decryption (requires S3EC v3 library)" << std::endl; - - std::cout << "\n--- v3 Security Enhancements ---" << std::endl; - std::cout << "šŸ”’ Enhanced Security Profile: Enforces authenticated encryption modes" << std::endl; - std::cout << "šŸ”’ Stricter Validation: More rigorous encryption context validation" << std::endl; - std::cout << "šŸ”’ Modern Cryptography: Uses latest cryptographic standards" << std::endl; - std::cout << "šŸ”’ Better Error Handling: More detailed error messages and validation" << std::endl; - - } else { - std::cerr << "āŒ Failed to generate data key: " << dataKeyOutcome.GetError().GetMessage() << std::endl; - Aws::ShutdownAPI(options); - return 1; - } - - std::cout << "\n=== Example completed successfully! ===" << std::endl; - std::cout << "\nšŸ“ NOTE: This example demonstrates the enhanced KMS integration that S3EC v3 uses." << std::endl; - std::cout << "v3 provides stricter security profiles and enhanced validation compared to v2." << std::endl; - std::cout << "To run the full S3 encryption client, you need to install the complete" << std::endl; - std::cout << "Amazon S3 Encryption Client library, which is not part of the standard AWS SDK." << std::endl; - std::cout << "\nFor the complete S3EC library, visit:" << std::endl; - std::cout << "https://github.com/aws/amazon-s3-encryption-client-cpp" << std::endl; - - } catch (const std::exception& e) { - std::cerr << "Exception occurred: " << e.what() << std::endl; - Aws::ShutdownAPI(options); - return 1; - } - - // Shutdown AWS SDK - Aws::ShutdownAPI(options); - return 0; -} diff --git a/all-examples/dotnet/v2/S3EncryptionExample.csproj b/all-examples/dotnet/v2/S3EncryptionExample.csproj deleted file mode 100644 index 9fd91363..00000000 --- a/all-examples/dotnet/v2/S3EncryptionExample.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net8.0 - enable - enable - - - - - - - - - - - - diff --git a/all-examples/dotnet/v3/S3EncryptionExample.csproj b/all-examples/dotnet/v3/S3EncryptionExample.csproj deleted file mode 100644 index 845a6cd1..00000000 --- a/all-examples/dotnet/v3/S3EncryptionExample.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - Exe - net8.0 - enable - enable - - - - - - - - - - - - diff --git a/all-examples/dotnet/v4/S3EncryptionExample.csproj b/all-examples/dotnet/v4/S3EncryptionExample.csproj deleted file mode 100644 index e0933854..00000000 --- a/all-examples/dotnet/v4/S3EncryptionExample.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - Exe - net8.0 - enable - enable - - - - - - - - - diff --git a/all-examples/go/v3/go.mod b/all-examples/go/v3/go.mod deleted file mode 100644 index 74c9c05d..00000000 --- a/all-examples/go/v3/go.mod +++ /dev/null @@ -1,11 +0,0 @@ -module github.com/aws/amazon-s3-encryption-client-python/all-examples/go/v3 - -go 1.21 - -require ( - github.com/aws/amazon-s3-encryption-client-go/v3 v3.1.1 - github.com/aws/aws-sdk-go-v2 v1.24.0 - github.com/aws/aws-sdk-go-v2/config v1.26.1 - github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 - github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 -) diff --git a/all-examples/go/v4/go.mod b/all-examples/go/v4/go.mod deleted file mode 100644 index fb5365b6..00000000 --- a/all-examples/go/v4/go.mod +++ /dev/null @@ -1,15 +0,0 @@ -module github.com/aws/amazon-s3-encryption-client-python/all-examples/go/v4 - -go 1.21 - -require ( - github.com/aws/amazon-s3-encryption-client-go/v4 v4.0.0 - github.com/aws/aws-sdk-go-v2 v1.24.0 - github.com/aws/aws-sdk-go-v2/config v1.26.1 - github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 - github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 -) - -// S3EC Go V4 is not released to pkg.go.dev as of writing. -// It is included as a submodule and referenced locally. -replace github.com/aws/amazon-s3-encryption-client-go/v4 => ./local-go-s3ec/v4 diff --git a/all-examples/java/v3/build.gradle.kts b/all-examples/java/v3/build.gradle.kts deleted file mode 100644 index 498ef757..00000000 --- a/all-examples/java/v3/build.gradle.kts +++ /dev/null @@ -1,27 +0,0 @@ -plugins { - `java-library` - application -} - -dependencies { - // S3 Encryption Client Java v3 - implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.5.0") - - // AWS SDK dependencies - implementation("software.amazon.awssdk:s3:2.31.66") - implementation("software.amazon.awssdk:kms:2.31.66") - implementation("software.amazon.awssdk:core:2.31.66") -} - -application { - mainClass = "com.example.S3EncryptionExample" -} - -repositories { - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} diff --git a/all-examples/java/v4/build.gradle.kts b/all-examples/java/v4/build.gradle.kts deleted file mode 100644 index 33ea0238..00000000 --- a/all-examples/java/v4/build.gradle.kts +++ /dev/null @@ -1,28 +0,0 @@ -plugins { - `java-library` - application -} - -dependencies { - // S3 Encryption Client Java v4 from local staging repository - implementation("software.amazon.encryption.s3:amazon-s3-encryption-client-java:3.4.0-IMPROVED") - - // AWS SDK dependencies - implementation("software.amazon.awssdk:s3:2.31.66") - implementation("software.amazon.awssdk:kms:2.31.66") - implementation("software.amazon.awssdk:core:2.31.66") -} - -application { - mainClass = "com.example.S3EncryptionExample" -} - -repositories { - mavenLocal() - mavenCentral() -} - -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} diff --git a/all-examples/php/v2/composer.json b/all-examples/php/v2/composer.json deleted file mode 100644 index ec32702b..00000000 --- a/all-examples/php/v2/composer.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "aws/s3ec-php-v2-example", - "description": "PHP v2 S3 Encryption Client example", - "type": "project", - "license": "Apache-2.0", - "repositories": [ - { - "type": "path", - "url": "./local-php-sdk", - "options": { - "symlink": true - } - } - ], - "require": { - "php": ">=7.4", - "aws/aws-sdk-php": "@dev" - }, - "autoload": { - "psr-4": { - "S3EC\\PhpV2Example\\": "src/" - } - }, - "config": { - "optimize-autoloader": true, - "platform": { - "php": "8.1" - } - } -} diff --git a/all-examples/php/v3/composer.json b/all-examples/php/v3/composer.json deleted file mode 100644 index a535ee38..00000000 --- a/all-examples/php/v3/composer.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "aws/s3ec-php-v3-example", - "description": "PHP v3 S3 Encryption Client example", - "type": "project", - "license": "Apache-2.0", - "repositories": [ - { - "type": "path", - "url": "./local-php-sdk", - "options": { - "symlink": true - } - } - ], - "require": { - "php": ">=7.4", - "aws/aws-sdk-php": "@dev" - }, - "autoload": { - "psr-4": { - "S3EC\\PhpV3Example\\": "src/" - } - }, - "config": { - "optimize-autoloader": true, - "platform": { - "php": "8.1" - } - } -} diff --git a/all-examples/ruby/v3/Gemfile b/all-examples/ruby/v3/Gemfile deleted file mode 100644 index ff13f9cd..00000000 --- a/all-examples/ruby/v3/Gemfile +++ /dev/null @@ -1,11 +0,0 @@ -source 'https://rubygems.org' - -ruby '~> 3.0' - -gem 'aws-sdk-s3', path: 'local-ruby-sdk/gems/aws-sdk-s3' -gem 'aws-sdk-kms', path: 'local-ruby-sdk/gems/aws-sdk-kms' -gem 'json', '~> 2.0' - -group :development do - gem 'rubocop', '~> 1.0' -end From 47d740f98e32c8c641977b878e3c5f9d2ed6913c Mon Sep 17 00:00:00 2001 From: Kess Plasmeier Date: Thu, 6 Nov 2025 14:53:08 -0800 Subject: [PATCH 03/18] cleanup --- all-examples/README.md | 25 +++++++------- all-examples/ruby/v2/main.rb | 63 ++++++++++++------------------------ 2 files changed, 33 insertions(+), 55 deletions(-) diff --git a/all-examples/README.md b/all-examples/README.md index 9f8aba4c..af3cba58 100644 --- a/all-examples/README.md +++ b/all-examples/README.md @@ -7,24 +7,23 @@ This directory contains example projects for the Amazon S3 Encryption Client acr Each language has subdirectories for different major versions of the S3 Encryption Client: - `cpp/` - C++ examples - - `v2/` - S3EC C++ v2 example - - `v3/` - S3EC C++ v3 example + - `v2/` - S3EC C++ v2 example (transitional) + - `v3/` - S3EC C++ v3 example (improved) - `dotnet/` - .NET examples - - `v2/` - S3EC .NET v2 example - - `v3/` - S3EC .NET v3 example - - `v4/` - S3EC .NET v4 example + - `v3/` - S3EC .NET v3 example (transitional) + - `v4/` - S3EC .NET v4 example (improved) - `go/` - Go examples - - `v3/` - S3EC Go v3 example - - `v4/` - S3EC Go v4 example + - `v3/` - S3EC Go v3 example (transitional) + - `v4/` - S3EC Go v4 example (improved) - `java/` - Java examples - - `v3/` - S3EC Java v3 example - - `v4/` - S3EC Java v4 example + - `v3/` - S3EC Java v3 example (transitional) + - `v4/` - S3EC Java v4 example (improved) - `php/` - PHP examples - - `v2/` - S3EC PHP v2 example - - `v3/` - S3EC PHP v3 example + - `v2/` - S3EC PHP v2 example (transitional) + - `v3/` - S3EC PHP v3 example (improved) - `ruby/` - Ruby examples - - `v2/` - S3EC Ruby v2 example - - `v3/` - S3EC Ruby v3 example + - `v2/` - S3EC Ruby v2 example (transitional) + - `v3/` - S3EC Ruby v3 example (improved) ## Setup Instructions diff --git a/all-examples/ruby/v2/main.rb b/all-examples/ruby/v2/main.rb index ce2e2641..55702da4 100644 --- a/all-examples/ruby/v2/main.rb +++ b/all-examples/ruby/v2/main.rb @@ -31,7 +31,7 @@ def main puts "Data length: #{test_data.length} bytes" puts - puts "--- Step 1: Initialize S3 Encryption Client v2 ---" + puts "--- Initialize S3 Encryption Client v2 ---" # Create regular S3 client s3_client = Aws::S3::Client.new(region: region) @@ -49,16 +49,10 @@ def main security_profile: :v2 ) - puts "āœ… Successfully initialized S3 Encryption Client v2" - puts " KMS Key ID: #{kms_key_id}" - puts " Key Wrap Schema: kms_context" - puts " Content Encryption Schema: aes_gcm_no_padding" - puts " Security Profile: v2" - puts - - puts "--- Step 2: Encrypt and Upload Object to S3 ---" + puts "Successfully initialized S3 Encryption Client v2" + puts "--- Encrypt and Upload Object to S3 ---" - # Optional: Add encryption context for additional security + # Add encryption context for additional security encryption_context = { 'purpose' => 'example', 'version' => 'v2', @@ -73,14 +67,13 @@ def main kms_encryption_context: encryption_context }) - puts "āœ… Successfully uploaded encrypted object to S3!" + puts "Successfully uploaded encrypted object to S3!" puts " Bucket: #{bucket_name}" puts " Key: #{object_key}" - puts " ETag: #{put_response.etag}" puts " Encryption Context: #{encryption_context}" puts - puts "--- Step 3: Download and Decrypt Object from S3 ---" + puts "--- Download and Decrypt Object from S3 ---" # Download and decrypt object using S3 Encryption Client get_response = encryption_client.get_object({ @@ -92,71 +85,57 @@ def main # Read the decrypted data decrypted_data = get_response.body.read - puts "āœ… Successfully downloaded and decrypted object from S3!" + puts "Successfully downloaded and decrypted object from S3!" puts " Object size: #{decrypted_data.length} bytes" puts " Decrypted data: #{decrypted_data}" puts - puts "--- Step 4: Verify Roundtrip Success ---" + puts "--- Verify Roundtrip Success ---" # Verify the roundtrip was successful if decrypted_data == test_data - puts "šŸŽ‰ SUCCESS: Roundtrip encryption/decryption completed successfully!" - puts " āœ… Original data matches decrypted data" - puts " āœ… Data integrity verified" + puts "SUCCESS: Roundtrip encryption/decryption completed successfully!" + puts " Original data matches decrypted data" + puts " Data integrity verified" else - puts "āŒ ERROR: Roundtrip failed - data mismatch" + puts "ERROR: Roundtrip failed - data mismatch" puts " Original: #{test_data}" puts " Decrypted: #{decrypted_data}" exit 1 end - - puts - puts "--- Step 5: Cleanup ---" - + # Optionally Delete the Object + #puts "--- Cleanup ---" # Clean up the test object using regular S3 client # s3_client.delete_object({ # bucket: bucket_name, # key: object_key # }) - - puts "āœ… Test object deleted from S3" + # puts "Test object deleted from S3" puts puts "=== Example completed successfully! ===" - puts - puts "šŸ“ This example demonstrates the Amazon S3 Encryption Client v2 for Ruby" - puts "performing a complete roundtrip of encrypting data during upload and" - puts "decrypting it during download, using AWS KMS for key management." - puts - puts "Key features demonstrated:" - puts "• Client-side encryption using AES-GCM" - puts "• KMS integration for key wrapping" - puts "• Encryption context for additional security" - puts "• Automatic key rotation and management" - puts "• Secure roundtrip data integrity verification" rescue Aws::S3::Errors::NoSuchBucket => e - puts "āŒ Error: S3 bucket '#{bucket_name}' does not exist or is not accessible" + puts "Error: S3 bucket '#{bucket_name}' does not exist or is not accessible" puts " #{e.message}" exit 1 rescue Aws::KMS::Errors::NotFoundException => e - puts "āŒ Error: KMS key '#{kms_key_id}' not found or not accessible" + puts "Error: KMS key '#{kms_key_id}' not found or not accessible" puts " #{e.message}" exit 1 rescue Aws::S3::EncryptionV2::Errors::EncryptionError => e - puts "āŒ S3 Encryption Error: #{e.message}" + puts "S3 Encryption Error: #{e.message}" exit 1 rescue Aws::S3::EncryptionV2::Errors::DecryptionError => e - puts "āŒ S3 Decryption Error: #{e.message}" + puts "S3 Decryption Error: #{e.message}" exit 1 rescue Aws::Errors::ServiceError => e - puts "āŒ AWS Service Error: #{e.message}" + puts "AWS Service Error: #{e.message}" puts " Error Code: #{e.code}" if e.respond_to?(:code) exit 1 rescue StandardError => e - puts "āŒ Unexpected error: #{e.message}" + puts "Unexpected error: #{e.message}" puts e.backtrace.first(5) exit 1 end From a475f8fa980e5f8c7d10152622d52f77aacdec7e Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Thu, 6 Nov 2025 16:57:36 -0800 Subject: [PATCH 04/18] m --- all-examples/go/v3/Makefile | 69 +++++++++++++ all-examples/go/v3/README.md | 102 ++++++++++++++++++ all-examples/go/v3/go.mod | 32 ++++++ all-examples/go/v3/go.sum | 40 +++++++ all-examples/go/v3/local-go-s3ec | 1 + all-examples/go/v3/main.go | 169 ++++++++++++++++++++++++++++++ all-examples/go/v4/Makefile | 69 +++++++++++++ all-examples/go/v4/README.md | 116 +++++++++++++++++++++ all-examples/go/v4/go.mod | 32 ++++++ all-examples/go/v4/go.sum | 40 +++++++ all-examples/go/v4/local-go-s3ec | 1 + all-examples/go/v4/main.go | 172 +++++++++++++++++++++++++++++++ 12 files changed, 843 insertions(+) create mode 100644 all-examples/go/v3/Makefile create mode 100644 all-examples/go/v3/README.md create mode 100644 all-examples/go/v3/go.mod create mode 100644 all-examples/go/v3/go.sum create mode 120000 all-examples/go/v3/local-go-s3ec create mode 100644 all-examples/go/v3/main.go create mode 100644 all-examples/go/v4/Makefile create mode 100644 all-examples/go/v4/README.md create mode 100644 all-examples/go/v4/go.mod create mode 100644 all-examples/go/v4/go.sum create mode 120000 all-examples/go/v4/local-go-s3ec create mode 100644 all-examples/go/v4/main.go diff --git a/all-examples/go/v3/Makefile b/all-examples/go/v3/Makefile new file mode 100644 index 00000000..1436211c --- /dev/null +++ b/all-examples/go/v3/Makefile @@ -0,0 +1,69 @@ +# Makefile for S3 Encryption Client Go v3 Example + +# Default target +.PHONY: all install clean run help + +# Variables +SCRIPT = main.go + +# Default arguments for running the example +# Override these when calling make run +BUCKET_NAME ?= avp-21638 +OBJECT_KEY ?= s3ec-go-v3 +KMS_KEY_ID ?= arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 +AWS_REGION ?= us-east-2 + +all: install + +# Install dependencies using Go modules +install: + @echo "Installing Go dependencies..." + @go mod tidy + @echo "Dependencies installed successfully!" + +# Clean Go artifacts +clean: + @echo "Cleaning Go artifacts..." + @go clean + @echo "Clean completed!" + +# Run the example with default arguments +run: install + @echo "Running S3 Encryption Client v3 Go example..." + @echo "Bucket: $(BUCKET_NAME)" + @echo "Object Key: $(OBJECT_KEY)" + @echo "KMS Key ID: $(KMS_KEY_ID)" + @echo "Region: $(AWS_REGION)" + @echo "" + @go run $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION) + +# Run with custom arguments +# Usage: make run-custom BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key AWS_REGION=my-region +run-custom: install + @go run $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION) + +# Show help +help: + @echo "S3 Encryption Client Go v3 Example Makefile" + @echo "" + @echo "Available targets:" + @echo " install - Install Go dependencies using Go modules" + @echo " run - Install dependencies and run the example with default parameters" + @echo " run-custom - Install dependencies and run with custom parameters" + @echo " clean - Remove Go artifacts" + @echo " help - Show this help message" + @echo "" + @echo "Default parameters:" + @echo " BUCKET_NAME = $(BUCKET_NAME)" + @echo " OBJECT_KEY = $(OBJECT_KEY)" + @echo " KMS_KEY_ID = $(KMS_KEY_ID)" + @echo " AWS_REGION = $(AWS_REGION)" + @echo "" + @echo "To run with custom parameters:" + @echo " make run BUCKET_NAME=your-bucket OBJECT_KEY=your-key KMS_KEY_ID=your-kms-key AWS_REGION=your-region" + @echo "" + @echo "Prerequisites:" + @echo " - Go 1.21+ installed on the system" + @echo " - AWS credentials configured (AWS CLI, environment variables, or IAM role)" + @echo " - Valid S3 bucket and KMS key with appropriate permissions" + @echo " - S3 Encryption Client v3 Go SDK (included in local-go-s3ec)" diff --git a/all-examples/go/v3/README.md b/all-examples/go/v3/README.md new file mode 100644 index 00000000..cd06a8dd --- /dev/null +++ b/all-examples/go/v3/README.md @@ -0,0 +1,102 @@ +# S3 Encryption Client Go v3 Example + +This example demonstrates how to use the Amazon S3 Encryption Client v3 for Go to perform client-side encryption and decryption of objects stored in Amazon S3. + +## Prerequisites + +1. **Go**: Requires Go 1.21 or later +2. **AWS Credentials**: Configure your AWS credentials using one of the following methods: + - AWS CLI: `aws configure` + - Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` + - IAM roles (for EC2 instances) +3. **KMS Key**: You'll need a KMS key ID or ARN. You can use the default example key: `arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01` +4. **S3 Bucket**: An existing S3 bucket where you have read/write permissions + +## Setup + +1. Initialize submodules and download dependencies: + ```bash + make init + ``` + + Or manually: + ```bash + git submodule update --init --recursive + go mod tidy + ``` + +## Usage + +### Using Make (Recommended) + +Run the example with default parameters: +```bash +make run +``` + +Run with custom parameters: +```bash +make run BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key AWS_REGION=my-region +``` + +Build the binary: +```bash +make build +``` + +Run directly without building: +```bash +make run-direct +``` + +### Manual Usage + +Run the example with the following command: + +```bash +go run main.go +``` + +### Example: + +```bash +go run main.go my-test-bucket s3ec-go-v3-test arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 us-east-2 +``` + +## What This Example Does + +1. **Initialize S3 Encryption Client v3**: Creates an S3 encryption client using KMS for key management +2. **Encrypt and Upload**: Encrypts test data and uploads it to the specified S3 bucket +3. **Download and Decrypt**: Downloads the encrypted object and decrypts it +4. **Verify Integrity**: Compares the original data with the decrypted data to ensure integrity +5. **Cleanup**: Optionally deletes the test object (commented out by default) + +## Key Features Demonstrated + +- **Client-side encryption** using AES-GCM +- **KMS integration** for key wrapping and management +- **Encryption context** for additional security +- **Automatic key rotation** and management +- **Secure roundtrip** data integrity verification + +## Security Profile + +This example uses S3 Encryption Client v3 with the following security features: +- **Key Wrap Schema**: kms_context +- **Content Encryption Schema**: aes_gcm_no_padding +- **Security Profile**: v3 (enhanced security) + +## Error Handling + +The example includes comprehensive error handling for common scenarios: +- Invalid AWS credentials +- Non-existent S3 buckets +- Inaccessible KMS keys +- Network connectivity issues +- Data integrity verification failures + +## Notes + +- The cleanup step (deleting the test object) is commented out by default to allow you to inspect the encrypted object in S3 +- Uncomment the cleanup code in Step 5 if you want the example to automatically delete the test object +- The example uses encryption context metadata for additional security diff --git a/all-examples/go/v3/go.mod b/all-examples/go/v3/go.mod new file mode 100644 index 00000000..1821569a --- /dev/null +++ b/all-examples/go/v3/go.mod @@ -0,0 +1,32 @@ +module github.com/aws/amazon-s3-encryption-client-python/all-examples/go/v3 + +go 1.24 + +require ( + github.com/aws/amazon-s3-encryption-client-go/v3 v3.1.0 + github.com/aws/aws-sdk-go-v2 v1.24.0 + github.com/aws/aws-sdk-go-v2/config v1.26.1 + github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 + github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 +) + +require ( + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.16.12 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.26.5 // indirect + github.com/aws/smithy-go v1.19.0 // indirect +) + +// S3EC Go V3 uses a local submodule for development +replace github.com/aws/amazon-s3-encryption-client-go/v3 => ./local-go-s3ec/v3 diff --git a/all-examples/go/v3/go.sum b/all-examples/go/v3/go.sum new file mode 100644 index 00000000..244c8814 --- /dev/null +++ b/all-examples/go/v3/go.sum @@ -0,0 +1,40 @@ +github.com/aws/aws-sdk-go-v2 v1.24.0 h1:890+mqQ+hTpNuw0gGP6/4akolQkSToDJgHfQE7AwGuk= +github.com/aws/aws-sdk-go-v2 v1.24.0/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 h1:OCs21ST2LrepDfD3lwlQiOqIGp6JiEUqG84GzTDoyJs= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4/go.mod h1:usURWEKSNNAcAZuzRn/9ZYPT8aZQkR7xcCtunK/LkJo= +github.com/aws/aws-sdk-go-v2/config v1.26.1 h1:z6DqMxclFGL3Zfo+4Q0rLnAZ6yVkzCRxhRMsiRQnD1o= +github.com/aws/aws-sdk-go-v2/config v1.26.1/go.mod h1:ZB+CuKHRbb5v5F0oJtGdhFTelmrxd4iWO1lf0rQwSAg= +github.com/aws/aws-sdk-go-v2/credentials v1.16.12 h1:v/WgB8NxprNvr5inKIiVVrXPuuTegM+K8nncFkr1usU= +github.com/aws/aws-sdk-go-v2/credentials v1.16.12/go.mod h1:X21k0FjEJe+/pauud82HYiQbEr9jRKY3kXEIQ4hXeTQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 h1:w98BT5w+ao1/r5sUuiH6JkVzjowOKeOJRHERyy1vh58= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10/go.mod h1:K2WGI7vUvkIv1HoNbfBA1bvIZ+9kL3YVmWxeKuLQsiw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 h1:v+HbZaCGmOwnTTVS86Fleq0vPzOd7tnJGbFhP0stNLs= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9/go.mod h1:Xjqy+Nyj7VDLBtCMkQYOw1QYfAEZCVLrfI0ezve8wd4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 h1:N94sVhRACtXyVcjXxrwK1SKFIJrA9pOJ5yu2eSHnmls= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9/go.mod h1:hqamLz7g1/4EJP+GH5NBhcUMLjW+gKLQabgyz6/7WAU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 h1:GrSw8s0Gs/5zZ0SX+gX4zQjRnRsMJDJ2sLur1gRBhEM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 h1:ugD6qzjYtB7zM5PN/ZIeaAIyefPaD82G8+SJopgvUpw= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9/go.mod h1:YD0aYBWCrPENpHolhKw2XDlTIWae2GKXT1T4o6N6hiM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 h1:/90OR2XbSYfXucBMJ4U14wrjlfleq/0SB6dZDPncgmo= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9/go.mod h1:dN/Of9/fNZet7UrQQ6kTDo/VSwKPIq94vjlU16bRARc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 h1:Nf2sHxjMJR8CSImIVCONRi4g0Su3J+TSTbS7G0pUeMU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9/go.mod h1:idky4TER38YIjr2cADF1/ugFMKvZV7p//pVeV5LZbF0= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 h1:iEAeF6YC3l4FzlJPP9H3Ko1TXpdjdqWffxXjp8SY6uk= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9/go.mod h1:kjsXoK23q9Z/tLBrckZLLyvjhZoS+AGrzqzUfEClvMM= +github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 h1:c75pHGBV3h6WOsIjbJhLyOnlCPXzap45nbiP2Z5jk5M= +github.com/aws/aws-sdk-go-v2/service/kms v1.27.4/go.mod h1:D9FVDkZjkZnnFHymJ3fPVz0zOUlNSd0xcIIVmmrAac8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 h1:Keso8lIOS+IzI2MkPZyK6G0LYcK3My2LQ+T5bxghEAY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5/go.mod h1:vADO6Jn+Rq4nDtfwNjhgR84qkZwiC6FqCaXdw/kYwjA= +github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 h1:ldSFWz9tEHAwHNmjx2Cvy1MjP5/L9kNoR0skc6wyOOM= +github.com/aws/aws-sdk-go-v2/service/sso v1.18.5/go.mod h1:CaFfXLYL376jgbP7VKC96uFcU8Rlavak0UlAwk1Dlhc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 h1:2k9KmFawS63euAkY4/ixVNsYYwrwnd5fIvgEKkfZFNM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5/go.mod h1:W+nd4wWDVkSUIox9bacmkBP5NMFQeTJ/xqNabpzSR38= +github.com/aws/aws-sdk-go-v2/service/sts v1.26.5 h1:5UYvv8JUvllZsRnfrcMQ+hJ9jNICmcgKPAO1CER25Wg= +github.com/aws/aws-sdk-go-v2/service/sts v1.26.5/go.mod h1:XX5gh4CB7wAs4KhcF46G6C8a2i7eupU19dcAAE+EydU= +github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM= +github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= diff --git a/all-examples/go/v3/local-go-s3ec b/all-examples/go/v3/local-go-s3ec new file mode 120000 index 00000000..7e5e770c --- /dev/null +++ b/all-examples/go/v3/local-go-s3ec @@ -0,0 +1 @@ +../../../test-server/go-v3-transition-server/local-go-s3ec \ No newline at end of file diff --git a/all-examples/go/v3/main.go b/all-examples/go/v3/main.go new file mode 100644 index 00000000..afb82f13 --- /dev/null +++ b/all-examples/go/v3/main.go @@ -0,0 +1,169 @@ +package main + +import ( + "context" + "fmt" + "io" + "os" + "strings" + + "github.com/aws/amazon-s3-encryption-client-go/v3/client" + "github.com/aws/amazon-s3-encryption-client-go/v3/materials" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/kms" + "github.com/aws/aws-sdk-go-v2/service/s3" +) + +func main() { + // Check command line arguments + if len(os.Args) != 5 { + fmt.Printf("Usage: %s \n", os.Args[0]) + fmt.Printf("Example: %s avp-21638 s3ec-go-v3 arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 us-east-2\n", os.Args[0]) + os.Exit(1) + } + + bucketName := os.Args[1] + objectKey := os.Args[2] + kmsKeyID := os.Args[3] + region := os.Args[4] + + fmt.Println("=== S3 Encryption Client v3 Example (Go) ===") + fmt.Printf("Bucket: %s\n", bucketName) + fmt.Printf("Object Key: %s\n", objectKey) + fmt.Printf("KMS Key ID: %s\n", kmsKeyID) + fmt.Printf("Region: %s\n", region) + fmt.Println() + + // Test data for encryption + testData := "Hello, World! This is a test message for S3 encryption client v3 in Go." + fmt.Printf("Original data: %s\n", testData) + fmt.Printf("Data length: %d bytes\n", len(testData)) + fmt.Println() + + fmt.Println("--- Initialize S3 Encryption Client v3 ---") + + // Create regular S3 client + cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region)) + if err != nil { + fmt.Printf("Error loading AWS config: %v\n", err) + os.Exit(1) + } + s3Client := s3.NewFromConfig(cfg) + + // Create KMS client + kmsClient := kms.NewFromConfig(cfg) + + // Create KMS keyring + keyring := materials.NewKmsKeyring(kmsClient, kmsKeyID) + + // Create Cryptographic Materials Manager + cmm, err := materials.NewCryptographicMaterialsManager(keyring) + if err != nil { + fmt.Printf("Error creating CMM: %v\n", err) + os.Exit(1) + } + + // Create S3 Encryption Client v3 + encryptionClient, err := client.New(s3Client, cmm) + if err != nil { + fmt.Printf("Error creating S3 Encryption Client: %v\n", err) + os.Exit(1) + } + + fmt.Println("Successfully initialized S3 Encryption Client v3") + fmt.Println("--- Encrypt and Upload Object to S3 ---") + + // Add encryption context for additional security + encryptionContext := map[string]string{ + "purpose": "example", + "version": "v3", + "language": "go", + } + + // Create context with encryption context + ctx := context.WithValue(context.Background(), "EncryptionContext", encryptionContext) + + // Upload encrypted object using S3 Encryption Client + putInput := &s3.PutObjectInput{ + Bucket: aws.String(bucketName), + Key: aws.String(objectKey), + Body: strings.NewReader(testData), + Metadata: encryptionContext, + } + + _, err = encryptionClient.PutObject(ctx, putInput) + if err != nil { + if strings.Contains(err.Error(), "NoSuchBucket") { + fmt.Printf("Error: S3 bucket '%s' does not exist or is not accessible\n", bucketName) + } else if strings.Contains(err.Error(), "NotFoundException") { + fmt.Printf("Error: KMS key '%s' not found or not accessible\n", kmsKeyID) + } else { + fmt.Printf("Error uploading encrypted object: %v\n", err) + } + os.Exit(1) + } + + fmt.Println("Successfully uploaded encrypted object to S3!") + fmt.Printf(" Bucket: %s\n", bucketName) + fmt.Printf(" Key: %s\n", objectKey) + fmt.Printf(" Encryption Context: %v\n", encryptionContext) + fmt.Println() + + fmt.Println("--- Download and Decrypt Object from S3 ---") + + // Download and decrypt object using S3 Encryption Client + getInput := &s3.GetObjectInput{ + Bucket: aws.String(bucketName), + Key: aws.String(objectKey), + } + + getResponse, err := encryptionClient.GetObject(ctx, getInput) + if err != nil { + fmt.Printf("Error downloading and decrypting object: %v\n", err) + os.Exit(1) + } + defer getResponse.Body.Close() + + // Read the decrypted data + decryptedData, err := io.ReadAll(getResponse.Body) + if err != nil { + fmt.Printf("Error reading decrypted data: %v\n", err) + os.Exit(1) + } + + fmt.Println("Successfully downloaded and decrypted object from S3!") + fmt.Printf(" Object size: %d bytes\n", len(decryptedData)) + fmt.Printf(" Decrypted data: %s\n", string(decryptedData)) + fmt.Println() + + fmt.Println("--- Verify Roundtrip Success ---") + + // Verify the roundtrip was successful + if string(decryptedData) == testData { + fmt.Println("SUCCESS: Roundtrip encryption/decryption completed successfully!") + fmt.Println(" Original data matches decrypted data") + fmt.Println(" Data integrity verified") + } else { + fmt.Println("ERROR: Roundtrip failed - data mismatch") + fmt.Printf(" Original: %s\n", testData) + fmt.Printf(" Decrypted: %s\n", string(decryptedData)) + os.Exit(1) + } + + // Optionally Delete the Object + //fmt.Println("--- Cleanup ---") + // Clean up the test object using regular S3 client + // _, err = s3Client.DeleteObject(context.TODO(), &s3.DeleteObjectInput{ + // Bucket: aws.String(bucketName), + // Key: aws.String(objectKey), + // }) + // if err != nil { + // fmt.Printf("Error deleting test object: %v\n", err) + // } else { + // fmt.Println("Test object deleted from S3") + // } + + fmt.Println() + fmt.Println("=== Example completed successfully! ===") +} diff --git a/all-examples/go/v4/Makefile b/all-examples/go/v4/Makefile new file mode 100644 index 00000000..1e8307e7 --- /dev/null +++ b/all-examples/go/v4/Makefile @@ -0,0 +1,69 @@ +# Makefile for S3 Encryption Client Go v4 Example + +# Default target +.PHONY: all install clean run help + +# Variables +SCRIPT = main.go + +# Default arguments for running the example +# Override these when calling make run +BUCKET_NAME ?= avp-21638 +OBJECT_KEY ?= s3ec-go-v4 +KMS_KEY_ID ?= arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 +AWS_REGION ?= us-east-2 + +all: install + +# Install dependencies using Go modules +install: + @echo "Installing Go dependencies..." + @go mod tidy + @echo "Dependencies installed successfully!" + +# Clean Go artifacts +clean: + @echo "Cleaning Go artifacts..." + @go clean + @echo "Clean completed!" + +# Run the example with default arguments +run: install + @echo "Running S3 Encryption Client v4 Go example..." + @echo "Bucket: $(BUCKET_NAME)" + @echo "Object Key: $(OBJECT_KEY)" + @echo "KMS Key ID: $(KMS_KEY_ID)" + @echo "Region: $(AWS_REGION)" + @echo "" + @go run $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION) + +# Run with custom arguments +# Usage: make run-custom BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key AWS_REGION=my-region +run-custom: install + @go run $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION) + +# Show help +help: + @echo "S3 Encryption Client Go v4 Example Makefile" + @echo "" + @echo "Available targets:" + @echo " install - Install Go dependencies using Go modules" + @echo " run - Install dependencies and run the example with default parameters" + @echo " run-custom - Install dependencies and run with custom parameters" + @echo " clean - Remove Go artifacts" + @echo " help - Show this help message" + @echo "" + @echo "Default parameters:" + @echo " BUCKET_NAME = $(BUCKET_NAME)" + @echo " OBJECT_KEY = $(OBJECT_KEY)" + @echo " KMS_KEY_ID = $(KMS_KEY_ID)" + @echo " AWS_REGION = $(AWS_REGION)" + @echo "" + @echo "To run with custom parameters:" + @echo " make run BUCKET_NAME=your-bucket OBJECT_KEY=your-key KMS_KEY_ID=your-kms-key AWS_REGION=your-region" + @echo "" + @echo "Prerequisites:" + @echo " - Go 1.24+ installed on the system" + @echo " - AWS credentials configured (AWS CLI, environment variables, or IAM role)" + @echo " - Valid S3 bucket and KMS key with appropriate permissions" + @echo " - S3 Encryption Client v4 Go SDK (included in local-go-s3ec)" diff --git a/all-examples/go/v4/README.md b/all-examples/go/v4/README.md new file mode 100644 index 00000000..319d912f --- /dev/null +++ b/all-examples/go/v4/README.md @@ -0,0 +1,116 @@ +# S3 Encryption Client Go v4 Example + +This example demonstrates how to use the Amazon S3 Encryption Client v4 for Go to perform client-side encryption and decryption of objects stored in Amazon S3 with enhanced security features including commitment policies. + +## Prerequisites + +1. **Go**: Requires Go 1.24 or later +2. **AWS Credentials**: Configure your AWS credentials using one of the following methods: + - AWS CLI: `aws configure` + - Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` + - IAM roles (for EC2 instances) +3. **KMS Key**: You'll need a KMS key ID or ARN. You can use the default example key: `arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01` +4. **S3 Bucket**: An existing S3 bucket where you have read/write permissions + +## Setup + +1. Initialize submodules and download dependencies: + ```bash + make init + ``` + + Or manually: + ```bash + git submodule update --init --recursive + go mod tidy + ``` + + **Note**: This example uses a local submodule for the S3EC Go v4 library via the `replace` directive in `go.mod`. + +## Usage + +### Using Make (Recommended) + +Run the example with default parameters: +```bash +make run +``` + +Run with custom parameters: +```bash +make run BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key AWS_REGION=my-region +``` + +Build the binary: +```bash +make build +``` + +Run directly without building: +```bash +make run-direct +``` + +### Manual Usage + +Run the example with the following command: + +```bash +go run main.go +``` + +### Example: + +```bash +go run main.go my-test-bucket s3ec-go-v4-test arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 us-east-2 +``` + +## What This Example Does + +1. **Initialize S3 Encryption Client v4**: Creates an S3 encryption client using KMS for key management with commitment policy +2. **Encrypt and Upload**: Encrypts test data and uploads it to the specified S3 bucket +3. **Download and Decrypt**: Downloads the encrypted object and decrypts it +4. **Verify Integrity**: Compares the original data with the decrypted data to ensure integrity +5. **Cleanup**: Optionally deletes the test object (commented out by default) + +## Key Features Demonstrated + +- **Client-side encryption** using AES-GCM +- **KMS integration** for key wrapping and management +- **Encryption context** for additional security +- **Commitment policy enforcement** for enhanced security +- **Automatic key rotation** and management +- **Secure roundtrip** data integrity verification + +## Security Profile + +This example uses S3 Encryption Client v4 with the following security features: +- **Key Wrap Schema**: kms_context +- **Content Encryption Schema**: aes_gcm_no_padding +- **Security Profile**: v4 (latest security enhancements) +- **Commitment Policy**: REQUIRE_ENCRYPT_ALLOW_DECRYPT (requires commitment on encryption, allows decryption of both committed and non-committed objects) + +## Commitment Policy + +S3 Encryption Client v4 introduces commitment policies to provide additional security guarantees: + +- **REQUIRE_ENCRYPT_REQUIRE_DECRYPT**: Requires commitment on both encryption and decryption +- **REQUIRE_ENCRYPT_ALLOW_DECRYPT**: Requires commitment on encryption, allows decryption of both committed and non-committed objects (used in this example) +- **FORBID_ENCRYPT_ALLOW_DECRYPT**: Forbids commitment on encryption, allows decryption of both committed and non-committed objects + +## Error Handling + +The example includes comprehensive error handling for common scenarios: +- Invalid AWS credentials +- Non-existent S3 buckets +- Inaccessible KMS keys +- Legacy wrapping algorithm errors +- Network connectivity issues +- Data integrity verification failures + +## Notes + +- The cleanup step (deleting the test object) is commented out by default to allow you to inspect the encrypted object in S3 +- Uncomment the cleanup code in Step 5 if you want the example to automatically delete the test object +- The example uses encryption context metadata for additional security +- If using a local version of S3EC Go v4, ensure the `replace` directive in `go.mod` points to the correct local path diff --git a/all-examples/go/v4/go.mod b/all-examples/go/v4/go.mod new file mode 100644 index 00000000..48bea56e --- /dev/null +++ b/all-examples/go/v4/go.mod @@ -0,0 +1,32 @@ +module github.com/aws/amazon-s3-encryption-client-python/all-examples/go/v4 + +go 1.24 + +require ( + github.com/aws/amazon-s3-encryption-client-go/v4 v4.0.0 + github.com/aws/aws-sdk-go-v2 v1.24.0 + github.com/aws/aws-sdk-go-v2/config v1.26.1 + github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 + github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 +) + +require ( + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.16.12 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.26.5 // indirect + github.com/aws/smithy-go v1.19.0 // indirect +) + +// S3EC Go V4 uses a local submodule for development +replace github.com/aws/amazon-s3-encryption-client-go/v4 => ./local-go-s3ec/v4 diff --git a/all-examples/go/v4/go.sum b/all-examples/go/v4/go.sum new file mode 100644 index 00000000..244c8814 --- /dev/null +++ b/all-examples/go/v4/go.sum @@ -0,0 +1,40 @@ +github.com/aws/aws-sdk-go-v2 v1.24.0 h1:890+mqQ+hTpNuw0gGP6/4akolQkSToDJgHfQE7AwGuk= +github.com/aws/aws-sdk-go-v2 v1.24.0/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 h1:OCs21ST2LrepDfD3lwlQiOqIGp6JiEUqG84GzTDoyJs= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4/go.mod h1:usURWEKSNNAcAZuzRn/9ZYPT8aZQkR7xcCtunK/LkJo= +github.com/aws/aws-sdk-go-v2/config v1.26.1 h1:z6DqMxclFGL3Zfo+4Q0rLnAZ6yVkzCRxhRMsiRQnD1o= +github.com/aws/aws-sdk-go-v2/config v1.26.1/go.mod h1:ZB+CuKHRbb5v5F0oJtGdhFTelmrxd4iWO1lf0rQwSAg= +github.com/aws/aws-sdk-go-v2/credentials v1.16.12 h1:v/WgB8NxprNvr5inKIiVVrXPuuTegM+K8nncFkr1usU= +github.com/aws/aws-sdk-go-v2/credentials v1.16.12/go.mod h1:X21k0FjEJe+/pauud82HYiQbEr9jRKY3kXEIQ4hXeTQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 h1:w98BT5w+ao1/r5sUuiH6JkVzjowOKeOJRHERyy1vh58= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10/go.mod h1:K2WGI7vUvkIv1HoNbfBA1bvIZ+9kL3YVmWxeKuLQsiw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 h1:v+HbZaCGmOwnTTVS86Fleq0vPzOd7tnJGbFhP0stNLs= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9/go.mod h1:Xjqy+Nyj7VDLBtCMkQYOw1QYfAEZCVLrfI0ezve8wd4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 h1:N94sVhRACtXyVcjXxrwK1SKFIJrA9pOJ5yu2eSHnmls= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9/go.mod h1:hqamLz7g1/4EJP+GH5NBhcUMLjW+gKLQabgyz6/7WAU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 h1:GrSw8s0Gs/5zZ0SX+gX4zQjRnRsMJDJ2sLur1gRBhEM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 h1:ugD6qzjYtB7zM5PN/ZIeaAIyefPaD82G8+SJopgvUpw= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9/go.mod h1:YD0aYBWCrPENpHolhKw2XDlTIWae2GKXT1T4o6N6hiM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 h1:/90OR2XbSYfXucBMJ4U14wrjlfleq/0SB6dZDPncgmo= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9/go.mod h1:dN/Of9/fNZet7UrQQ6kTDo/VSwKPIq94vjlU16bRARc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 h1:Nf2sHxjMJR8CSImIVCONRi4g0Su3J+TSTbS7G0pUeMU= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9/go.mod h1:idky4TER38YIjr2cADF1/ugFMKvZV7p//pVeV5LZbF0= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 h1:iEAeF6YC3l4FzlJPP9H3Ko1TXpdjdqWffxXjp8SY6uk= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9/go.mod h1:kjsXoK23q9Z/tLBrckZLLyvjhZoS+AGrzqzUfEClvMM= +github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 h1:c75pHGBV3h6WOsIjbJhLyOnlCPXzap45nbiP2Z5jk5M= +github.com/aws/aws-sdk-go-v2/service/kms v1.27.4/go.mod h1:D9FVDkZjkZnnFHymJ3fPVz0zOUlNSd0xcIIVmmrAac8= +github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 h1:Keso8lIOS+IzI2MkPZyK6G0LYcK3My2LQ+T5bxghEAY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5/go.mod h1:vADO6Jn+Rq4nDtfwNjhgR84qkZwiC6FqCaXdw/kYwjA= +github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 h1:ldSFWz9tEHAwHNmjx2Cvy1MjP5/L9kNoR0skc6wyOOM= +github.com/aws/aws-sdk-go-v2/service/sso v1.18.5/go.mod h1:CaFfXLYL376jgbP7VKC96uFcU8Rlavak0UlAwk1Dlhc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 h1:2k9KmFawS63euAkY4/ixVNsYYwrwnd5fIvgEKkfZFNM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5/go.mod h1:W+nd4wWDVkSUIox9bacmkBP5NMFQeTJ/xqNabpzSR38= +github.com/aws/aws-sdk-go-v2/service/sts v1.26.5 h1:5UYvv8JUvllZsRnfrcMQ+hJ9jNICmcgKPAO1CER25Wg= +github.com/aws/aws-sdk-go-v2/service/sts v1.26.5/go.mod h1:XX5gh4CB7wAs4KhcF46G6C8a2i7eupU19dcAAE+EydU= +github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM= +github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= diff --git a/all-examples/go/v4/local-go-s3ec b/all-examples/go/v4/local-go-s3ec new file mode 120000 index 00000000..d06737d9 --- /dev/null +++ b/all-examples/go/v4/local-go-s3ec @@ -0,0 +1 @@ +../../../test-server/go-v4-server/local-go-s3ec \ No newline at end of file diff --git a/all-examples/go/v4/main.go b/all-examples/go/v4/main.go new file mode 100644 index 00000000..bda2af6a --- /dev/null +++ b/all-examples/go/v4/main.go @@ -0,0 +1,172 @@ +package main + +import ( + "context" + "fmt" + "io" + "os" + "strings" + + "github.com/aws/amazon-s3-encryption-client-go/v4/client" + "github.com/aws/amazon-s3-encryption-client-go/v4/commitment" + "github.com/aws/amazon-s3-encryption-client-go/v4/materials" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/kms" + "github.com/aws/aws-sdk-go-v2/service/s3" +) + +func main() { + // Check command line arguments + if len(os.Args) != 5 { + fmt.Printf("Usage: %s \n", os.Args[0]) + fmt.Printf("Example: %s avp-21638 s3ec-go-v4 arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 us-east-2\n", os.Args[0]) + os.Exit(1) + } + + bucketName := os.Args[1] + objectKey := os.Args[2] + kmsKeyID := os.Args[3] + region := os.Args[4] + + fmt.Println("=== S3 Encryption Client v4 Example (Go) ===") + fmt.Printf("Bucket: %s\n", bucketName) + fmt.Printf("Object Key: %s\n", objectKey) + fmt.Printf("KMS Key ID: %s\n", kmsKeyID) + fmt.Printf("Region: %s\n", region) + fmt.Println() + + // Test data for encryption + testData := "Hello, World! This is a test message for S3 encryption client v4 in Go." + fmt.Printf("Original data: %s\n", testData) + fmt.Printf("Data length: %d bytes\n", len(testData)) + fmt.Println() + + fmt.Println("--- Initialize S3 Encryption Client v4 ---") + + // Create regular S3 client + cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region)) + if err != nil { + fmt.Printf("Error loading AWS config: %v\n", err) + os.Exit(1) + } + s3Client := s3.NewFromConfig(cfg) + + // Create KMS client + kmsClient := kms.NewFromConfig(cfg) + + // Create KMS keyring + keyring := materials.NewKmsKeyring(kmsClient, kmsKeyID) + + // Create Cryptographic Materials Manager + cmm, err := materials.NewCryptographicMaterialsManager(keyring) + if err != nil { + fmt.Printf("Error creating CMM: %v\n", err) + os.Exit(1) + } + + // Create S3 Encryption Client v4 + encryptionClient, err := client.New(s3Client, cmm, func(options *client.EncryptionClientOptions) { + options.CommitmentPolicy = commitment.REQUIRE_ENCRYPT_ALLOW_DECRYPT + }) + if err != nil { + fmt.Printf("Error creating S3 Encryption Client: %v\n", err) + os.Exit(1) + } + + fmt.Println("Successfully initialized S3 Encryption Client v4") + fmt.Println("--- Encrypt and Upload Object to S3 ---") + + // Add encryption context + encryptionContext := map[string]string{ + "purpose": "example", + "version": "v4", + "language": "go", + } + + // Create context with encryption context + ctx := context.WithValue(context.Background(), "EncryptionContext", encryptionContext) + + // Upload encrypted object using S3 Encryption Client + putInput := &s3.PutObjectInput{ + Bucket: aws.String(bucketName), + Key: aws.String(objectKey), + Body: strings.NewReader(testData), + Metadata: encryptionContext, + } + + _, err = encryptionClient.PutObject(ctx, putInput) + if err != nil { + if strings.Contains(err.Error(), "NoSuchBucket") { + fmt.Printf("Error: S3 bucket '%s' does not exist or is not accessible\n", bucketName) + } else if strings.Contains(err.Error(), "NotFoundException") { + fmt.Printf("Error: KMS key '%s' not found or not accessible\n", kmsKeyID) + } else { + fmt.Printf("Error uploading encrypted object: %v\n", err) + } + os.Exit(1) + } + + fmt.Println("Successfully uploaded encrypted object to S3!") + fmt.Printf(" Bucket: %s\n", bucketName) + fmt.Printf(" Key: %s\n", objectKey) + fmt.Printf(" Encryption Context: %v\n", encryptionContext) + fmt.Println() + + fmt.Println("--- Download and Decrypt Object from S3 ---") + + // Download and decrypt object using S3 Encryption Client + getInput := &s3.GetObjectInput{ + Bucket: aws.String(bucketName), + Key: aws.String(objectKey), + } + + getResponse, err := encryptionClient.GetObject(ctx, getInput) + if err != nil { + fmt.Printf("Error downloading and decrypting object: %v\n", err) + os.Exit(1) + } + defer getResponse.Body.Close() + + // Read the decrypted data + decryptedData, err := io.ReadAll(getResponse.Body) + if err != nil { + fmt.Printf("Error reading decrypted data: %v\n", err) + os.Exit(1) + } + + fmt.Println("Successfully downloaded and decrypted object from S3!") + fmt.Printf(" Object size: %d bytes\n", len(decryptedData)) + fmt.Printf(" Decrypted data: %s\n", string(decryptedData)) + fmt.Println() + + fmt.Println("--- Verify Roundtrip Success ---") + + // Verify the roundtrip was successful + if string(decryptedData) == testData { + fmt.Println("SUCCESS: Roundtrip encryption/decryption completed successfully!") + fmt.Println(" Original data matches decrypted data") + fmt.Println(" Data integrity verified") + } else { + fmt.Println("ERROR: Roundtrip failed - data mismatch") + fmt.Printf(" Original: %s\n", testData) + fmt.Printf(" Decrypted: %s\n", string(decryptedData)) + os.Exit(1) + } + + // Optionally Delete the Object + //fmt.Println("--- Cleanup ---") + // Clean up the test object using regular S3 client + // _, err = s3Client.DeleteObject(context.TODO(), &s3.DeleteObjectInput{ + // Bucket: aws.String(bucketName), + // Key: aws.String(objectKey), + // }) + // if err != nil { + // fmt.Printf("Error deleting test object: %v\n", err) + // } else { + // fmt.Println("Test object deleted from S3") + // } + + fmt.Println() + fmt.Println("=== Example completed successfully! ===") +} From 5162f828cbb6419ebb42a4a3048e71f95699240e Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 10:34:40 -0800 Subject: [PATCH 05/18] m --- .github/workflows/main.yml | 8 +++ all-examples/Makefile | 110 +++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 all-examples/Makefile diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 52c3e465..d53b9dca 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,3 +35,11 @@ jobs: name: Run Duvet uses: ./.github/workflows/duvet.yml secrets: inherit + + run-examples: + permissions: + id-token: write + contents: read + name: Run Examples + uses: ./.github/workflows/examples.yml + secrets: inherit diff --git a/all-examples/Makefile b/all-examples/Makefile new file mode 100644 index 00000000..eb854edc --- /dev/null +++ b/all-examples/Makefile @@ -0,0 +1,110 @@ +# Makefile for S3 Encryption Client Examples +# Runs make commands across all language/version directories + +# Default target +.PHONY: all install clean run help list-examples + +# Find all directories with Makefiles +EXAMPLE_DIRS := $(shell find . -name Makefile -not -path "./Makefile" | xargs dirname | sed 's|^\./||' | $(if $(FILTER),grep -E "$$(echo '$(FILTER)' | sed 's/,/|/g')",cat) | sort) + +all: install + +# Install dependencies for all examples +install: + @echo "Installing dependencies for all examples..." + @failed=0; \ + for dir in $(EXAMPLE_DIRS); do \ + echo ""; \ + echo "=== Installing dependencies in $$dir ==="; \ + if cd $$dir && $(MAKE) install && cd - > /dev/null; then \ + echo "āœ“ Successfully installed dependencies in $$dir"; \ + else \ + echo "āœ— Failed to install dependencies in $$dir"; \ + failed=$$((failed + 1)); \ + fi; \ + done; \ + echo ""; \ + if [ $$failed -eq 0 ]; then \ + echo "All dependencies installed successfully!"; \ + else \ + echo "$$failed example(s) failed to install dependencies"; \ + exit 1; \ + fi + +# Clean all examples +clean: + @echo "Cleaning all examples..." + @failed=0; \ + for dir in $(EXAMPLE_DIRS); do \ + echo ""; \ + echo "=== Cleaning $$dir ==="; \ + if cd $$dir && $(MAKE) clean && cd - > /dev/null; then \ + echo "āœ“ Successfully cleaned $$dir"; \ + else \ + echo "āœ— Failed to clean $$dir"; \ + failed=$$((failed + 1)); \ + fi; \ + done; \ + echo ""; \ + if [ $$failed -eq 0 ]; then \ + echo "All examples cleaned successfully!"; \ + else \ + echo "$$failed example(s) failed to clean"; \ + exit 1; \ + fi + +# Run all examples with default parameters +run: + @echo "Running all examples with default parameters..." + @failed=0; \ + for dir in $(EXAMPLE_DIRS); do \ + echo ""; \ + echo "=== Running example in $$dir ==="; \ + if cd $$dir && $(MAKE) run && cd - > /dev/null; then \ + echo "āœ“ Successfully ran example in $$dir"; \ + else \ + echo "āœ— Failed to run example in $$dir"; \ + failed=$$((failed + 1)); \ + fi; \ + done; \ + echo ""; \ + if [ $$failed -eq 0 ]; then \ + echo "All examples completed successfully!"; \ + else \ + echo "$$failed example(s) failed to run"; \ + exit 1; \ + fi + +# List all available examples +list-examples: + @echo "Available S3 Encryption Client examples:" + @for dir in $(EXAMPLE_DIRS); do \ + echo " $$dir"; \ + done + +# Show help +help: + @echo "S3 Encryption Client Examples Makefile" + @echo "" + @echo "Available targets:" + @echo " install - Install dependencies for all examples" + @echo " run - Run all examples with default parameters" + @echo " clean - Clean all examples" + @echo " list-examples - List all available example directories" + @echo " help - Show this help message" + @echo "" + @echo "Filtering examples:" + @echo " Use FILTER to run commands on specific examples:" + @echo " make install FILTER=go # Only Go examples" + @echo " make run FILTER=v4 # Only v4 examples" + @echo " make clean FILTER=go/v3,ruby # Go v3 and Ruby examples" + @echo "" + @echo "Individual example usage:" + @echo " To work with a specific example, cd into its directory and use its Makefile:" + @echo " cd go/v4 && make run" + @echo " cd ruby/v2 && make install" + @echo "" + @echo "Available examples:" + @for dir in $(EXAMPLE_DIRS); do \ + echo " $$dir"; \ + done From 88255308597d77de9d3b1e978385d0f822527e46 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 10:38:47 -0800 Subject: [PATCH 06/18] m --- .github/workflows/examples.yml | 115 +++++++++++++++++++++++++++++++++ all-examples/go/v3/README.md | 2 +- 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/examples.yml diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml new file mode 100644 index 00000000..880b4c33 --- /dev/null +++ b/.github/workflows/examples.yml @@ -0,0 +1,115 @@ +name: Run Examples + +on: + workflow_call: + +jobs: + run-examples: + runs-on: macos-14-large + permissions: + id-token: write + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + submodules: true + token: ${{ secrets.PAT_FOR_PRIVATE_RUBY }} + + - name: Checkout CPP code for cpp-v2-transition + uses: actions/checkout@v5 + with: + submodules: recursive + token: ${{ secrets.PAT_FOR_CPP }} + repository: awslabs/aws-sdk-cpp-staging + ref: fire-egg-dev + path: test-server/cpp-v2-transition-server/aws-sdk-cpp/ + + - name: Checkout CPP code cpp-v3 + uses: actions/checkout@v5 + with: + submodules: recursive + token: ${{ secrets.PAT_FOR_CPP }} + repository: awslabs/aws-sdk-cpp-staging + ref: fire-egg-dev + path: test-server/cpp-v3-server/aws-sdk-cpp/ + + - name: Checkout .NET V2 code + uses: actions/checkout@v5 + with: + token: ${{ secrets.PAT_FOR_DOTNET }} + repository: aws/private-amazon-s3-encryption-client-dotnet-staging + ref: v3sdk-development + path: test-server/net-v2-v3-server/s3ec-net-v2/ + + - name: Checkout .NET V3 code + uses: actions/checkout@v5 + with: + token: ${{ secrets.PAT_FOR_DOTNET }} + repository: aws/private-amazon-s3-encryption-client-dotnet-staging + ref: s3ec-v3 + path: test-server/net-v2-v3-server/s3ec-net-v3 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: "3.4" + + - name: Set up PHP with Composer + uses: shivammathur/setup-php@verbose + with: + php-version: "8.1" + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.25 + + # Cache uv dependencies + - name: Cache uv dependencies + uses: actions/cache@v3 + with: + path: ~/.cache/uv + key: ${{ runner.os }}-uv-${{ hashFiles('./test-server/python-v3-server/**/pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-uv- + + - name: Install Uv + run: pip install uv + + # Cache Gradle dependencies and build outputs + - name: Cache Gradle packages + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + test-server/java-v3-server/.gradle + test-server/java-tests/.gradle + key: ${{ runner.os }}-gradle-${{ hashFiles('test-server/java-v3-server/**/*.gradle*', 'test-server/java-tests/**/gradle-wrapper.properties', 'test-server/java-tests/**/*.gradle*', 'test-server/java-v3-server/**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::370957321024:role/S3EC-Python-Github-test-role + aws-region: us-west-2 + + - name: Install dependencies for all examples + working-directory: ./all-examples + run: make install + + - name: Run all examples + working-directory: ./all-examples + run: make run + env: + AWS_REGION: us-west-2 + TEST_BUCKET: ${{ vars.TEST_SERVER_S3_BUCKET }} + TEST_KMS_KEY: ${{ vars.TEST_SERVER_KMS_KEY_ARN }} diff --git a/all-examples/go/v3/README.md b/all-examples/go/v3/README.md index cd06a8dd..e6a48488 100644 --- a/all-examples/go/v3/README.md +++ b/all-examples/go/v3/README.md @@ -4,7 +4,7 @@ This example demonstrates how to use the Amazon S3 Encryption Client v3 for Go t ## Prerequisites -1. **Go**: Requires Go 1.21 or later +1. **Go**: Requires Go 1.24 or later 2. **AWS Credentials**: Configure your AWS credentials using one of the following methods: - AWS CLI: `aws configure` - Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` From 21428255b9d1776a235a794e931cb20dfbcc1de6 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 10:51:35 -0800 Subject: [PATCH 07/18] m --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 880b4c33..3104ea54 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout code uses: actions/checkout@v5 with: - submodules: true + submodules: recursive token: ${{ secrets.PAT_FOR_PRIVATE_RUBY }} - name: Checkout CPP code for cpp-v2-transition From adc13db4dc4812d8178a72f5bd8830eda2b812d5 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 11:09:35 -0800 Subject: [PATCH 08/18] m --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitmodules b/.gitmodules index 7cb8cc1b..d1462eb2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,6 +12,9 @@ path = test-server/php-v3-server/local-php-sdk url = git@github.com:aws/private-aws-sdk-php-staging.git branch = s3ec/improved +[submodule "test-server/go-v3-transition-server/local-go-s3ec"] + path = test-server/go-v3-transition-server/local-go-s3ec + url = https://github.com/aws/private-amazon-s3-encryption-client-go-staging [submodule "test-server/go-v4-server/local-go-s3ec"] path = test-server/go-v4-server/local-go-s3ec url = https://github.com/aws/private-amazon-s3-encryption-client-go-staging From ca3fb9534e8074fec8639c6e8bbd97cc48c5c768 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 11:11:46 -0800 Subject: [PATCH 09/18] m --- .gitmodules | 3 - all-examples/go/v3/Makefile | 69 ------------- all-examples/go/v3/README.md | 102 ------------------- all-examples/go/v3/go.mod | 32 ------ all-examples/go/v3/go.sum | 40 -------- all-examples/go/v3/local-go-s3ec | 1 - all-examples/go/v3/main.go | 169 ------------------------------- 7 files changed, 416 deletions(-) delete mode 100644 all-examples/go/v3/Makefile delete mode 100644 all-examples/go/v3/README.md delete mode 100644 all-examples/go/v3/go.mod delete mode 100644 all-examples/go/v3/go.sum delete mode 120000 all-examples/go/v3/local-go-s3ec delete mode 100644 all-examples/go/v3/main.go diff --git a/.gitmodules b/.gitmodules index d1462eb2..7cb8cc1b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,9 +12,6 @@ path = test-server/php-v3-server/local-php-sdk url = git@github.com:aws/private-aws-sdk-php-staging.git branch = s3ec/improved -[submodule "test-server/go-v3-transition-server/local-go-s3ec"] - path = test-server/go-v3-transition-server/local-go-s3ec - url = https://github.com/aws/private-amazon-s3-encryption-client-go-staging [submodule "test-server/go-v4-server/local-go-s3ec"] path = test-server/go-v4-server/local-go-s3ec url = https://github.com/aws/private-amazon-s3-encryption-client-go-staging diff --git a/all-examples/go/v3/Makefile b/all-examples/go/v3/Makefile deleted file mode 100644 index 1436211c..00000000 --- a/all-examples/go/v3/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# Makefile for S3 Encryption Client Go v3 Example - -# Default target -.PHONY: all install clean run help - -# Variables -SCRIPT = main.go - -# Default arguments for running the example -# Override these when calling make run -BUCKET_NAME ?= avp-21638 -OBJECT_KEY ?= s3ec-go-v3 -KMS_KEY_ID ?= arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 -AWS_REGION ?= us-east-2 - -all: install - -# Install dependencies using Go modules -install: - @echo "Installing Go dependencies..." - @go mod tidy - @echo "Dependencies installed successfully!" - -# Clean Go artifacts -clean: - @echo "Cleaning Go artifacts..." - @go clean - @echo "Clean completed!" - -# Run the example with default arguments -run: install - @echo "Running S3 Encryption Client v3 Go example..." - @echo "Bucket: $(BUCKET_NAME)" - @echo "Object Key: $(OBJECT_KEY)" - @echo "KMS Key ID: $(KMS_KEY_ID)" - @echo "Region: $(AWS_REGION)" - @echo "" - @go run $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION) - -# Run with custom arguments -# Usage: make run-custom BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key AWS_REGION=my-region -run-custom: install - @go run $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION) - -# Show help -help: - @echo "S3 Encryption Client Go v3 Example Makefile" - @echo "" - @echo "Available targets:" - @echo " install - Install Go dependencies using Go modules" - @echo " run - Install dependencies and run the example with default parameters" - @echo " run-custom - Install dependencies and run with custom parameters" - @echo " clean - Remove Go artifacts" - @echo " help - Show this help message" - @echo "" - @echo "Default parameters:" - @echo " BUCKET_NAME = $(BUCKET_NAME)" - @echo " OBJECT_KEY = $(OBJECT_KEY)" - @echo " KMS_KEY_ID = $(KMS_KEY_ID)" - @echo " AWS_REGION = $(AWS_REGION)" - @echo "" - @echo "To run with custom parameters:" - @echo " make run BUCKET_NAME=your-bucket OBJECT_KEY=your-key KMS_KEY_ID=your-kms-key AWS_REGION=your-region" - @echo "" - @echo "Prerequisites:" - @echo " - Go 1.21+ installed on the system" - @echo " - AWS credentials configured (AWS CLI, environment variables, or IAM role)" - @echo " - Valid S3 bucket and KMS key with appropriate permissions" - @echo " - S3 Encryption Client v3 Go SDK (included in local-go-s3ec)" diff --git a/all-examples/go/v3/README.md b/all-examples/go/v3/README.md deleted file mode 100644 index e6a48488..00000000 --- a/all-examples/go/v3/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# S3 Encryption Client Go v3 Example - -This example demonstrates how to use the Amazon S3 Encryption Client v3 for Go to perform client-side encryption and decryption of objects stored in Amazon S3. - -## Prerequisites - -1. **Go**: Requires Go 1.24 or later -2. **AWS Credentials**: Configure your AWS credentials using one of the following methods: - - AWS CLI: `aws configure` - - Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` - - IAM roles (for EC2 instances) -3. **KMS Key**: You'll need a KMS key ID or ARN. You can use the default example key: `arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01` -4. **S3 Bucket**: An existing S3 bucket where you have read/write permissions - -## Setup - -1. Initialize submodules and download dependencies: - ```bash - make init - ``` - - Or manually: - ```bash - git submodule update --init --recursive - go mod tidy - ``` - -## Usage - -### Using Make (Recommended) - -Run the example with default parameters: -```bash -make run -``` - -Run with custom parameters: -```bash -make run BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key AWS_REGION=my-region -``` - -Build the binary: -```bash -make build -``` - -Run directly without building: -```bash -make run-direct -``` - -### Manual Usage - -Run the example with the following command: - -```bash -go run main.go -``` - -### Example: - -```bash -go run main.go my-test-bucket s3ec-go-v3-test arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 us-east-2 -``` - -## What This Example Does - -1. **Initialize S3 Encryption Client v3**: Creates an S3 encryption client using KMS for key management -2. **Encrypt and Upload**: Encrypts test data and uploads it to the specified S3 bucket -3. **Download and Decrypt**: Downloads the encrypted object and decrypts it -4. **Verify Integrity**: Compares the original data with the decrypted data to ensure integrity -5. **Cleanup**: Optionally deletes the test object (commented out by default) - -## Key Features Demonstrated - -- **Client-side encryption** using AES-GCM -- **KMS integration** for key wrapping and management -- **Encryption context** for additional security -- **Automatic key rotation** and management -- **Secure roundtrip** data integrity verification - -## Security Profile - -This example uses S3 Encryption Client v3 with the following security features: -- **Key Wrap Schema**: kms_context -- **Content Encryption Schema**: aes_gcm_no_padding -- **Security Profile**: v3 (enhanced security) - -## Error Handling - -The example includes comprehensive error handling for common scenarios: -- Invalid AWS credentials -- Non-existent S3 buckets -- Inaccessible KMS keys -- Network connectivity issues -- Data integrity verification failures - -## Notes - -- The cleanup step (deleting the test object) is commented out by default to allow you to inspect the encrypted object in S3 -- Uncomment the cleanup code in Step 5 if you want the example to automatically delete the test object -- The example uses encryption context metadata for additional security diff --git a/all-examples/go/v3/go.mod b/all-examples/go/v3/go.mod deleted file mode 100644 index 1821569a..00000000 --- a/all-examples/go/v3/go.mod +++ /dev/null @@ -1,32 +0,0 @@ -module github.com/aws/amazon-s3-encryption-client-python/all-examples/go/v3 - -go 1.24 - -require ( - github.com/aws/amazon-s3-encryption-client-go/v3 v3.1.0 - github.com/aws/aws-sdk-go-v2 v1.24.0 - github.com/aws/aws-sdk-go-v2/config v1.26.1 - github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 - github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 -) - -require ( - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.16.12 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.26.5 // indirect - github.com/aws/smithy-go v1.19.0 // indirect -) - -// S3EC Go V3 uses a local submodule for development -replace github.com/aws/amazon-s3-encryption-client-go/v3 => ./local-go-s3ec/v3 diff --git a/all-examples/go/v3/go.sum b/all-examples/go/v3/go.sum deleted file mode 100644 index 244c8814..00000000 --- a/all-examples/go/v3/go.sum +++ /dev/null @@ -1,40 +0,0 @@ -github.com/aws/aws-sdk-go-v2 v1.24.0 h1:890+mqQ+hTpNuw0gGP6/4akolQkSToDJgHfQE7AwGuk= -github.com/aws/aws-sdk-go-v2 v1.24.0/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 h1:OCs21ST2LrepDfD3lwlQiOqIGp6JiEUqG84GzTDoyJs= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4/go.mod h1:usURWEKSNNAcAZuzRn/9ZYPT8aZQkR7xcCtunK/LkJo= -github.com/aws/aws-sdk-go-v2/config v1.26.1 h1:z6DqMxclFGL3Zfo+4Q0rLnAZ6yVkzCRxhRMsiRQnD1o= -github.com/aws/aws-sdk-go-v2/config v1.26.1/go.mod h1:ZB+CuKHRbb5v5F0oJtGdhFTelmrxd4iWO1lf0rQwSAg= -github.com/aws/aws-sdk-go-v2/credentials v1.16.12 h1:v/WgB8NxprNvr5inKIiVVrXPuuTegM+K8nncFkr1usU= -github.com/aws/aws-sdk-go-v2/credentials v1.16.12/go.mod h1:X21k0FjEJe+/pauud82HYiQbEr9jRKY3kXEIQ4hXeTQ= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10 h1:w98BT5w+ao1/r5sUuiH6JkVzjowOKeOJRHERyy1vh58= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.10/go.mod h1:K2WGI7vUvkIv1HoNbfBA1bvIZ+9kL3YVmWxeKuLQsiw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 h1:v+HbZaCGmOwnTTVS86Fleq0vPzOd7tnJGbFhP0stNLs= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9/go.mod h1:Xjqy+Nyj7VDLBtCMkQYOw1QYfAEZCVLrfI0ezve8wd4= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 h1:N94sVhRACtXyVcjXxrwK1SKFIJrA9pOJ5yu2eSHnmls= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9/go.mod h1:hqamLz7g1/4EJP+GH5NBhcUMLjW+gKLQabgyz6/7WAU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2 h1:GrSw8s0Gs/5zZ0SX+gX4zQjRnRsMJDJ2sLur1gRBhEM= -github.com/aws/aws-sdk-go-v2/internal/ini v1.7.2/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 h1:ugD6qzjYtB7zM5PN/ZIeaAIyefPaD82G8+SJopgvUpw= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9/go.mod h1:YD0aYBWCrPENpHolhKw2XDlTIWae2GKXT1T4o6N6hiM= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 h1:/90OR2XbSYfXucBMJ4U14wrjlfleq/0SB6dZDPncgmo= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9/go.mod h1:dN/Of9/fNZet7UrQQ6kTDo/VSwKPIq94vjlU16bRARc= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 h1:Nf2sHxjMJR8CSImIVCONRi4g0Su3J+TSTbS7G0pUeMU= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9/go.mod h1:idky4TER38YIjr2cADF1/ugFMKvZV7p//pVeV5LZbF0= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 h1:iEAeF6YC3l4FzlJPP9H3Ko1TXpdjdqWffxXjp8SY6uk= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9/go.mod h1:kjsXoK23q9Z/tLBrckZLLyvjhZoS+AGrzqzUfEClvMM= -github.com/aws/aws-sdk-go-v2/service/kms v1.27.4 h1:c75pHGBV3h6WOsIjbJhLyOnlCPXzap45nbiP2Z5jk5M= -github.com/aws/aws-sdk-go-v2/service/kms v1.27.4/go.mod h1:D9FVDkZjkZnnFHymJ3fPVz0zOUlNSd0xcIIVmmrAac8= -github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5 h1:Keso8lIOS+IzI2MkPZyK6G0LYcK3My2LQ+T5bxghEAY= -github.com/aws/aws-sdk-go-v2/service/s3 v1.47.5/go.mod h1:vADO6Jn+Rq4nDtfwNjhgR84qkZwiC6FqCaXdw/kYwjA= -github.com/aws/aws-sdk-go-v2/service/sso v1.18.5 h1:ldSFWz9tEHAwHNmjx2Cvy1MjP5/L9kNoR0skc6wyOOM= -github.com/aws/aws-sdk-go-v2/service/sso v1.18.5/go.mod h1:CaFfXLYL376jgbP7VKC96uFcU8Rlavak0UlAwk1Dlhc= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5 h1:2k9KmFawS63euAkY4/ixVNsYYwrwnd5fIvgEKkfZFNM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.5/go.mod h1:W+nd4wWDVkSUIox9bacmkBP5NMFQeTJ/xqNabpzSR38= -github.com/aws/aws-sdk-go-v2/service/sts v1.26.5 h1:5UYvv8JUvllZsRnfrcMQ+hJ9jNICmcgKPAO1CER25Wg= -github.com/aws/aws-sdk-go-v2/service/sts v1.26.5/go.mod h1:XX5gh4CB7wAs4KhcF46G6C8a2i7eupU19dcAAE+EydU= -github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM= -github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= diff --git a/all-examples/go/v3/local-go-s3ec b/all-examples/go/v3/local-go-s3ec deleted file mode 120000 index 7e5e770c..00000000 --- a/all-examples/go/v3/local-go-s3ec +++ /dev/null @@ -1 +0,0 @@ -../../../test-server/go-v3-transition-server/local-go-s3ec \ No newline at end of file diff --git a/all-examples/go/v3/main.go b/all-examples/go/v3/main.go deleted file mode 100644 index afb82f13..00000000 --- a/all-examples/go/v3/main.go +++ /dev/null @@ -1,169 +0,0 @@ -package main - -import ( - "context" - "fmt" - "io" - "os" - "strings" - - "github.com/aws/amazon-s3-encryption-client-go/v3/client" - "github.com/aws/amazon-s3-encryption-client-go/v3/materials" - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/config" - "github.com/aws/aws-sdk-go-v2/service/kms" - "github.com/aws/aws-sdk-go-v2/service/s3" -) - -func main() { - // Check command line arguments - if len(os.Args) != 5 { - fmt.Printf("Usage: %s \n", os.Args[0]) - fmt.Printf("Example: %s avp-21638 s3ec-go-v3 arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 us-east-2\n", os.Args[0]) - os.Exit(1) - } - - bucketName := os.Args[1] - objectKey := os.Args[2] - kmsKeyID := os.Args[3] - region := os.Args[4] - - fmt.Println("=== S3 Encryption Client v3 Example (Go) ===") - fmt.Printf("Bucket: %s\n", bucketName) - fmt.Printf("Object Key: %s\n", objectKey) - fmt.Printf("KMS Key ID: %s\n", kmsKeyID) - fmt.Printf("Region: %s\n", region) - fmt.Println() - - // Test data for encryption - testData := "Hello, World! This is a test message for S3 encryption client v3 in Go." - fmt.Printf("Original data: %s\n", testData) - fmt.Printf("Data length: %d bytes\n", len(testData)) - fmt.Println() - - fmt.Println("--- Initialize S3 Encryption Client v3 ---") - - // Create regular S3 client - cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region)) - if err != nil { - fmt.Printf("Error loading AWS config: %v\n", err) - os.Exit(1) - } - s3Client := s3.NewFromConfig(cfg) - - // Create KMS client - kmsClient := kms.NewFromConfig(cfg) - - // Create KMS keyring - keyring := materials.NewKmsKeyring(kmsClient, kmsKeyID) - - // Create Cryptographic Materials Manager - cmm, err := materials.NewCryptographicMaterialsManager(keyring) - if err != nil { - fmt.Printf("Error creating CMM: %v\n", err) - os.Exit(1) - } - - // Create S3 Encryption Client v3 - encryptionClient, err := client.New(s3Client, cmm) - if err != nil { - fmt.Printf("Error creating S3 Encryption Client: %v\n", err) - os.Exit(1) - } - - fmt.Println("Successfully initialized S3 Encryption Client v3") - fmt.Println("--- Encrypt and Upload Object to S3 ---") - - // Add encryption context for additional security - encryptionContext := map[string]string{ - "purpose": "example", - "version": "v3", - "language": "go", - } - - // Create context with encryption context - ctx := context.WithValue(context.Background(), "EncryptionContext", encryptionContext) - - // Upload encrypted object using S3 Encryption Client - putInput := &s3.PutObjectInput{ - Bucket: aws.String(bucketName), - Key: aws.String(objectKey), - Body: strings.NewReader(testData), - Metadata: encryptionContext, - } - - _, err = encryptionClient.PutObject(ctx, putInput) - if err != nil { - if strings.Contains(err.Error(), "NoSuchBucket") { - fmt.Printf("Error: S3 bucket '%s' does not exist or is not accessible\n", bucketName) - } else if strings.Contains(err.Error(), "NotFoundException") { - fmt.Printf("Error: KMS key '%s' not found or not accessible\n", kmsKeyID) - } else { - fmt.Printf("Error uploading encrypted object: %v\n", err) - } - os.Exit(1) - } - - fmt.Println("Successfully uploaded encrypted object to S3!") - fmt.Printf(" Bucket: %s\n", bucketName) - fmt.Printf(" Key: %s\n", objectKey) - fmt.Printf(" Encryption Context: %v\n", encryptionContext) - fmt.Println() - - fmt.Println("--- Download and Decrypt Object from S3 ---") - - // Download and decrypt object using S3 Encryption Client - getInput := &s3.GetObjectInput{ - Bucket: aws.String(bucketName), - Key: aws.String(objectKey), - } - - getResponse, err := encryptionClient.GetObject(ctx, getInput) - if err != nil { - fmt.Printf("Error downloading and decrypting object: %v\n", err) - os.Exit(1) - } - defer getResponse.Body.Close() - - // Read the decrypted data - decryptedData, err := io.ReadAll(getResponse.Body) - if err != nil { - fmt.Printf("Error reading decrypted data: %v\n", err) - os.Exit(1) - } - - fmt.Println("Successfully downloaded and decrypted object from S3!") - fmt.Printf(" Object size: %d bytes\n", len(decryptedData)) - fmt.Printf(" Decrypted data: %s\n", string(decryptedData)) - fmt.Println() - - fmt.Println("--- Verify Roundtrip Success ---") - - // Verify the roundtrip was successful - if string(decryptedData) == testData { - fmt.Println("SUCCESS: Roundtrip encryption/decryption completed successfully!") - fmt.Println(" Original data matches decrypted data") - fmt.Println(" Data integrity verified") - } else { - fmt.Println("ERROR: Roundtrip failed - data mismatch") - fmt.Printf(" Original: %s\n", testData) - fmt.Printf(" Decrypted: %s\n", string(decryptedData)) - os.Exit(1) - } - - // Optionally Delete the Object - //fmt.Println("--- Cleanup ---") - // Clean up the test object using regular S3 client - // _, err = s3Client.DeleteObject(context.TODO(), &s3.DeleteObjectInput{ - // Bucket: aws.String(bucketName), - // Key: aws.String(objectKey), - // }) - // if err != nil { - // fmt.Printf("Error deleting test object: %v\n", err) - // } else { - // fmt.Println("Test object deleted from S3") - // } - - fmt.Println() - fmt.Println("=== Example completed successfully! ===") -} From 6360e62df89ab1d543c1e7b4a70da02f723b99b3 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 11:22:19 -0800 Subject: [PATCH 10/18] m --- all-examples/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/all-examples/Makefile b/all-examples/Makefile index eb854edc..7dac8ce6 100644 --- a/all-examples/Makefile +++ b/all-examples/Makefile @@ -16,7 +16,7 @@ install: for dir in $(EXAMPLE_DIRS); do \ echo ""; \ echo "=== Installing dependencies in $$dir ==="; \ - if cd $$dir && $(MAKE) install && cd - > /dev/null; then \ + if (cd $$dir && $(MAKE) install); then \ echo "āœ“ Successfully installed dependencies in $$dir"; \ else \ echo "āœ— Failed to install dependencies in $$dir"; \ @@ -38,7 +38,7 @@ clean: for dir in $(EXAMPLE_DIRS); do \ echo ""; \ echo "=== Cleaning $$dir ==="; \ - if cd $$dir && $(MAKE) clean && cd - > /dev/null; then \ + if (cd $$dir && $(MAKE) clean); then \ echo "āœ“ Successfully cleaned $$dir"; \ else \ echo "āœ— Failed to clean $$dir"; \ @@ -60,7 +60,7 @@ run: for dir in $(EXAMPLE_DIRS); do \ echo ""; \ echo "=== Running example in $$dir ==="; \ - if cd $$dir && $(MAKE) run && cd - > /dev/null; then \ + if (cd $$dir && $(MAKE) run); then \ echo "āœ“ Successfully ran example in $$dir"; \ else \ echo "āœ— Failed to run example in $$dir"; \ From 1b838de18ed52eb24c8e4a3f781ebb58a9dc4002 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 12:24:39 -0800 Subject: [PATCH 11/18] m --- all-examples/go/v4/main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/all-examples/go/v4/main.go b/all-examples/go/v4/main.go index bda2af6a..a1227790 100644 --- a/all-examples/go/v4/main.go +++ b/all-examples/go/v4/main.go @@ -92,7 +92,6 @@ func main() { Bucket: aws.String(bucketName), Key: aws.String(objectKey), Body: strings.NewReader(testData), - Metadata: encryptionContext, } _, err = encryptionClient.PutObject(ctx, putInput) From 4e4ca9b2baabd45061224bfd1d0b84019e3a1195 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 12:44:05 -0800 Subject: [PATCH 12/18] m --- test-server/go-v4-server/local-go-s3ec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-server/go-v4-server/local-go-s3ec b/test-server/go-v4-server/local-go-s3ec index 6a2a7fe0..9946186d 160000 --- a/test-server/go-v4-server/local-go-s3ec +++ b/test-server/go-v4-server/local-go-s3ec @@ -1 +1 @@ -Subproject commit 6a2a7fe0418ceebc1b555c0f79b6328896e81939 +Subproject commit 9946186d6b760074750a535b663d6c84c5815308 From acdce5bac38c139f23fb064e0d2cbb055bfd5225 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 13:39:43 -0800 Subject: [PATCH 13/18] m --- .github/workflows/examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 3104ea54..ff99bcd9 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -111,5 +111,5 @@ jobs: run: make run env: AWS_REGION: us-west-2 - TEST_BUCKET: ${{ vars.TEST_SERVER_S3_BUCKET }} - TEST_KMS_KEY: ${{ vars.TEST_SERVER_KMS_KEY_ARN }} + BUCKET_NAME: ${{ vars.TEST_SERVER_S3_BUCKET }} + KMS_KEY_ID: ${{ vars.TEST_SERVER_KMS_KEY_ARN }} From f51d54dc93abb8f5e1bfdd359c7bedd10d530455 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Fri, 7 Nov 2025 14:35:11 -0800 Subject: [PATCH 14/18] m --- all-examples/go/v4/README.md | 65 ++---------------------------------- 1 file changed, 2 insertions(+), 63 deletions(-) diff --git a/all-examples/go/v4/README.md b/all-examples/go/v4/README.md index 319d912f..b6972f26 100644 --- a/all-examples/go/v4/README.md +++ b/all-examples/go/v4/README.md @@ -1,6 +1,6 @@ # S3 Encryption Client Go v4 Example -This example demonstrates how to use the Amazon S3 Encryption Client v4 for Go to perform client-side encryption and decryption of objects stored in Amazon S3 with enhanced security features including commitment policies. +This example demonstrates how to use the Amazon S3 Encryption Client v4 for Go to perform client-side encryption and decryption of objects. ## Prerequisites @@ -16,12 +16,11 @@ This example demonstrates how to use the Amazon S3 Encryption Client v4 for Go t 1. Initialize submodules and download dependencies: ```bash - make init + make install ``` Or manually: ```bash - git submodule update --init --recursive go mod tidy ``` @@ -41,16 +40,6 @@ Run with custom parameters: make run BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key AWS_REGION=my-region ``` -Build the binary: -```bash -make build -``` - -Run directly without building: -```bash -make run-direct -``` - ### Manual Usage Run the example with the following command: @@ -64,53 +53,3 @@ go run main.go ```bash go run main.go my-test-bucket s3ec-go-v4-test arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 us-east-2 ``` - -## What This Example Does - -1. **Initialize S3 Encryption Client v4**: Creates an S3 encryption client using KMS for key management with commitment policy -2. **Encrypt and Upload**: Encrypts test data and uploads it to the specified S3 bucket -3. **Download and Decrypt**: Downloads the encrypted object and decrypts it -4. **Verify Integrity**: Compares the original data with the decrypted data to ensure integrity -5. **Cleanup**: Optionally deletes the test object (commented out by default) - -## Key Features Demonstrated - -- **Client-side encryption** using AES-GCM -- **KMS integration** for key wrapping and management -- **Encryption context** for additional security -- **Commitment policy enforcement** for enhanced security -- **Automatic key rotation** and management -- **Secure roundtrip** data integrity verification - -## Security Profile - -This example uses S3 Encryption Client v4 with the following security features: -- **Key Wrap Schema**: kms_context -- **Content Encryption Schema**: aes_gcm_no_padding -- **Security Profile**: v4 (latest security enhancements) -- **Commitment Policy**: REQUIRE_ENCRYPT_ALLOW_DECRYPT (requires commitment on encryption, allows decryption of both committed and non-committed objects) - -## Commitment Policy - -S3 Encryption Client v4 introduces commitment policies to provide additional security guarantees: - -- **REQUIRE_ENCRYPT_REQUIRE_DECRYPT**: Requires commitment on both encryption and decryption -- **REQUIRE_ENCRYPT_ALLOW_DECRYPT**: Requires commitment on encryption, allows decryption of both committed and non-committed objects (used in this example) -- **FORBID_ENCRYPT_ALLOW_DECRYPT**: Forbids commitment on encryption, allows decryption of both committed and non-committed objects - -## Error Handling - -The example includes comprehensive error handling for common scenarios: -- Invalid AWS credentials -- Non-existent S3 buckets -- Inaccessible KMS keys -- Legacy wrapping algorithm errors -- Network connectivity issues -- Data integrity verification failures - -## Notes - -- The cleanup step (deleting the test object) is commented out by default to allow you to inspect the encrypted object in S3 -- Uncomment the cleanup code in Step 5 if you want the example to automatically delete the test object -- The example uses encryption context metadata for additional security -- If using a local version of S3EC Go v4, ensure the `replace` directive in `go.mod` points to the correct local path From ac9178126eacfae92a067a375f65e22ce70d5db4 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 10 Nov 2025 14:32:30 -0800 Subject: [PATCH 15/18] m --- .github/workflows/examples.yml | 2 +- .gitmodules | 3 --- all-examples/README.md | 8 -------- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index ff99bcd9..5fcdfb1e 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -69,7 +69,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: 1.25 + go-version: 1.24 # Cache uv dependencies - name: Cache uv dependencies diff --git a/.gitmodules b/.gitmodules index 1f9961e4..fe27b90e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -44,9 +44,6 @@ path = test-server/net-v2-v3-server/s3ec-net-v3 url = https://github.com/aws/private-amazon-s3-encryption-client-dotnet-staging.git branch = s3ec-v3 -[submodule "all-examples/ruby/v2/local-ruby-sdk"] - path = all-examples/ruby/v2/local-ruby-sdk - url = git@github.com:aws/aws-sdk-ruby-staging.git [submodule "test-server/net-v3-transition-server/s3ec-v3-transition-branch"] path = test-server/net-v3-transition-server/s3ec-v3-transition-branch url = https://github.com/aws/private-amazon-s3-encryption-client-dotnet-staging.git diff --git a/all-examples/README.md b/all-examples/README.md index ab446274..af3cba58 100644 --- a/all-examples/README.md +++ b/all-examples/README.md @@ -55,10 +55,6 @@ Each language directory contains specific setup instructions in its README file. ## Usage Each example directory contains: -<<<<<<< HEAD -======= - ->>>>>>> fireegg-test-servers - Build configuration files (e.g., `build.gradle.kts`, `go.mod`, `composer.json`) - Source code demonstrating basic S3EC usage - README with specific setup and run instructions @@ -66,10 +62,6 @@ Each example directory contains: ## Dependencies Examples use different dependency sources based on version: -<<<<<<< HEAD -======= - ->>>>>>> fireegg-test-servers - **Released versions**: Use public package repositories (Maven Central, npm, etc.) - **Staging versions**: Use git submodules pointing to staging repositories - **Local versions**: Reference locally built libraries From b53029aa00fd1fcc61dd294f53d87e095a0c16f1 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 10 Nov 2025 14:33:32 -0800 Subject: [PATCH 16/18] m --- all-examples/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/all-examples/README.md b/all-examples/README.md index af3cba58..59bc2d6c 100644 --- a/all-examples/README.md +++ b/all-examples/README.md @@ -30,6 +30,7 @@ Each language has subdirectories for different major versions of the S3 Encrypti ### Prerequisites 1. **Git Submodules**: Some examples depend on staging versions of the S3EC libraries that are included as git submodules. Initialize and update submodules: + ```bash git submodule update --init --recursive ``` @@ -55,6 +56,7 @@ Each language directory contains specific setup instructions in its README file. ## Usage Each example directory contains: + - Build configuration files (e.g., `build.gradle.kts`, `go.mod`, `composer.json`) - Source code demonstrating basic S3EC usage - README with specific setup and run instructions @@ -62,6 +64,7 @@ Each example directory contains: ## Dependencies Examples use different dependency sources based on version: + - **Released versions**: Use public package repositories (Maven Central, npm, etc.) - **Staging versions**: Use git submodules pointing to staging repositories - **Local versions**: Reference locally built libraries From c627fa8d538826299e1869585df812ad4ea76dc6 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 10 Nov 2025 14:38:51 -0800 Subject: [PATCH 17/18] m --- .github/workflows/examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 5fcdfb1e..30e47a06 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout code uses: actions/checkout@v5 with: - submodules: recursive + submodules: true token: ${{ secrets.PAT_FOR_PRIVATE_RUBY }} - name: Checkout CPP code for cpp-v2-transition From 387daa7b27d9b7a4b7f3bd9163a836ee16b16b20 Mon Sep 17 00:00:00 2001 From: Lucas McDonald Date: Mon, 10 Nov 2025 15:47:26 -0800 Subject: [PATCH 18/18] m --- all-examples/ruby/v2/main.rb | 3 +++ all-examples/ruby/v3/main.rb | 3 +++ 2 files changed, 6 insertions(+) diff --git a/all-examples/ruby/v2/main.rb b/all-examples/ruby/v2/main.rb index 51d85cc9..3fc86f7c 100644 --- a/all-examples/ruby/v2/main.rb +++ b/all-examples/ruby/v2/main.rb @@ -4,6 +4,9 @@ require 'aws-sdk-kms' require 'json' +# See: https://github.com/ruby/openssl/issues/949 +Aws.use_bundled_cert! + def main # Check command line arguments if ARGV.length != 4 diff --git a/all-examples/ruby/v3/main.rb b/all-examples/ruby/v3/main.rb index fb15f317..59743515 100644 --- a/all-examples/ruby/v3/main.rb +++ b/all-examples/ruby/v3/main.rb @@ -4,6 +4,9 @@ require 'aws-sdk-kms' require 'json' +# See: https://github.com/ruby/openssl/issues/949 +Aws.use_bundled_cert! + def main # Check command line arguments if ARGV.length != 4