Skip to content

Commit fec0319

Browse files
kessplasseebeeslucasmcdonald3
authored
add all-examples directory, Ruby V2/V3 example (#64)
* add v3 Ruby example (#68) Co-authored-by: Kess Plasmeier <76071473+kessplas@users.noreply.github.com> --------- Co-authored-by: seebees <ryanemer@amazon.com> Co-authored-by: Lucas McDonald <lucasmcdonald3@gmail.com>
1 parent 7468927 commit fec0319

10 files changed

Lines changed: 614 additions & 0 deletions

File tree

all-examples/README.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# S3 Encryption Client Examples
2+
3+
This directory contains example projects for the Amazon S3 Encryption Client across different programming languages and major versions.
4+
5+
## Directory Structure
6+
7+
Each language has subdirectories for different major versions of the S3 Encryption Client:
8+
9+
- `cpp/` - C++ examples
10+
- `v2/` - S3EC C++ v2 example (transitional)
11+
- `v3/` - S3EC C++ v3 example (improved)
12+
- `dotnet/` - .NET examples
13+
- `v3/` - S3EC .NET v3 example (transitional)
14+
- `v4/` - S3EC .NET v4 example (improved)
15+
- `go/` - Go examples
16+
- `v3/` - S3EC Go v3 example (transitional)
17+
- `v4/` - S3EC Go v4 example (improved)
18+
- `java/` - Java examples
19+
- `v3/` - S3EC Java v3 example (transitional)
20+
- `v4/` - S3EC Java v4 example (improved)
21+
- `php/` - PHP examples
22+
- `v2/` - S3EC PHP v2 example (transitional)
23+
- `v3/` - S3EC PHP v3 example (improved)
24+
- `ruby/` - Ruby examples
25+
- `v2/` - S3EC Ruby v2 example (transitional)
26+
- `v3/` - S3EC Ruby v3 example (improved)
27+
28+
## Setup Instructions
29+
30+
### Prerequisites
31+
32+
1. **Git Submodules**: Some examples depend on staging versions of the S3EC libraries that are included as git submodules. Initialize and update submodules:
33+
34+
```bash
35+
git submodule update --init --recursive
36+
```
37+
38+
2. **AWS Credentials**: Configure your AWS credentials using one of the following methods:
39+
- AWS CLI: `aws configure`
40+
- Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
41+
- IAM roles (for EC2 instances)
42+
43+
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.
44+
45+
### Language-Specific Setup
46+
47+
Each language directory contains specific setup instructions in its README file. Generally:
48+
49+
- **Java**: Requires JDK 11+ and Gradle
50+
- **Go**: Requires Go 1.21+
51+
- **.NET**: Requires .NET 8.0+
52+
- **PHP**: Requires PHP 7.4+ and Composer
53+
- **Ruby**: Requires Ruby 3.0+ and Bundler
54+
- **C++**: Requires CMake 3.16+ and C++17 compiler
55+
56+
## Usage
57+
58+
Each example directory contains:
59+
60+
- Build configuration files (e.g., `build.gradle.kts`, `go.mod`, `composer.json`)
61+
- Source code demonstrating basic S3EC usage
62+
- README with specific setup and run instructions
63+
64+
## Dependencies
65+
66+
Examples use different dependency sources based on version:
67+
68+
- **Released versions**: Use public package repositories (Maven Central, npm, etc.)
69+
- **Staging versions**: Use git submodules pointing to staging repositories
70+
- **Local versions**: Reference locally built libraries
71+
72+
## Support
73+
74+
For issues with specific examples, refer to the individual README files in each language/version directory.

all-examples/ruby/v2/Gemfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
source 'https://rubygems.org'
2+
3+
ruby '>= 2.7.0'
4+
5+
gem 'aws-sdk-s3', path: 'local-ruby-sdk/gems/aws-sdk-s3'
6+
gem 'aws-sdk-kms', path: 'local-ruby-sdk/gems/aws-sdk-kms'
7+
gem 'json', '~> 2.0'
8+
gem 'rexml', '~> 3.0'
9+
10+
group :development do
11+
gem 'rubocop', '~> 1.0'
12+
end

all-examples/ruby/v2/Gemfile.lock

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
PATH
2+
remote: local-ruby-sdk/gems/aws-sdk-kms
3+
specs:
4+
aws-sdk-kms (1.115.0)
5+
aws-sdk-core (~> 3, >= 3.234.0)
6+
aws-sigv4 (~> 1.5)
7+
8+
PATH
9+
remote: local-ruby-sdk/gems/aws-sdk-s3
10+
specs:
11+
aws-sdk-s3 (1.201.0)
12+
aws-sdk-core (~> 3, >= 3.234.0)
13+
aws-sdk-kms (~> 1)
14+
aws-sigv4 (~> 1.5)
15+
16+
GEM
17+
remote: https://rubygems.org/
18+
specs:
19+
ast (2.4.3)
20+
aws-eventstream (1.4.0)
21+
aws-partitions (1.1177.0)
22+
aws-sdk-core (3.235.0)
23+
aws-eventstream (~> 1, >= 1.3.0)
24+
aws-partitions (~> 1, >= 1.992.0)
25+
aws-sigv4 (~> 1.9)
26+
base64
27+
bigdecimal
28+
jmespath (~> 1, >= 1.6.1)
29+
logger
30+
aws-sigv4 (1.12.1)
31+
aws-eventstream (~> 1, >= 1.0.2)
32+
base64 (0.3.0)
33+
bigdecimal (3.3.1)
34+
jmespath (1.6.2)
35+
json (2.15.2)
36+
language_server-protocol (3.17.0.5)
37+
lint_roller (1.1.0)
38+
logger (1.7.0)
39+
parallel (1.27.0)
40+
parser (3.3.10.0)
41+
ast (~> 2.4.1)
42+
racc
43+
prism (1.6.0)
44+
racc (1.8.1)
45+
rainbow (3.1.1)
46+
regexp_parser (2.11.3)
47+
rexml (3.4.4)
48+
rubocop (1.81.6)
49+
json (~> 2.3)
50+
language_server-protocol (~> 3.17.0.2)
51+
lint_roller (~> 1.1.0)
52+
parallel (~> 1.10)
53+
parser (>= 3.3.0.2)
54+
rainbow (>= 2.2.2, < 4.0)
55+
regexp_parser (>= 2.9.3, < 3.0)
56+
rubocop-ast (>= 1.47.1, < 2.0)
57+
ruby-progressbar (~> 1.7)
58+
unicode-display_width (>= 2.4.0, < 4.0)
59+
rubocop-ast (1.47.1)
60+
parser (>= 3.3.7.2)
61+
prism (~> 1.4)
62+
ruby-progressbar (1.13.0)
63+
unicode-display_width (3.2.0)
64+
unicode-emoji (~> 4.1)
65+
unicode-emoji (4.1.0)
66+
67+
PLATFORMS
68+
arm64-darwin-24
69+
ruby
70+
71+
DEPENDENCIES
72+
aws-sdk-kms!
73+
aws-sdk-s3!
74+
json (~> 2.0)
75+
rexml (~> 3.0)
76+
rubocop (~> 1.0)
77+
78+
RUBY VERSION
79+
ruby 3.4.7p58
80+
81+
BUNDLED WITH
82+
2.7.2

all-examples/ruby/v2/Makefile

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Makefile for S3 Encryption Client Ruby v2 Example
2+
3+
# Default target
4+
.PHONY: all install clean run help
5+
6+
# Variables
7+
SCRIPT = main.rb
8+
9+
# Default arguments for running the example
10+
# Override these when calling make run
11+
BUCKET_NAME ?= avp-21638
12+
OBJECT_KEY ?= s3ec-ruby-v2
13+
KMS_KEY_ID ?= arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01
14+
AWS_REGION ?= us-east-2
15+
16+
all: install
17+
18+
# Install dependencies using Bundler
19+
install:
20+
@echo "Installing Ruby dependencies..."
21+
@bundle install
22+
@echo "Dependencies installed successfully!"
23+
24+
# Clean bundle artifacts
25+
clean:
26+
@echo "Cleaning bundle artifacts..."
27+
@bundle clean --force
28+
@echo "Clean completed!"
29+
30+
# Run the example with default arguments
31+
run: install
32+
@echo "Running S3 Encryption Client v2 Ruby example..."
33+
@echo "Bucket: $(BUCKET_NAME)"
34+
@echo "Object Key: $(OBJECT_KEY)"
35+
@echo "KMS Key ID: $(KMS_KEY_ID)"
36+
@echo "Region: $(AWS_REGION)"
37+
@echo ""
38+
@bundle exec ruby $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION)
39+
40+
# Run with custom arguments
41+
# Usage: make run-custom BUCKET_NAME=my-bucket OBJECT_KEY=my-key KMS_KEY_ID=my-kms-key AWS_REGION=my-region
42+
run-custom: install
43+
@bundle exec ruby $(SCRIPT) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION)
44+
45+
# Show help
46+
help:
47+
@echo "S3 Encryption Client Ruby v2 Example Makefile"
48+
@echo ""
49+
@echo "Available targets:"
50+
@echo " install - Install Ruby dependencies using Bundler"
51+
@echo " run - Install dependencies and run the example with default parameters"
52+
@echo " run-custom - Install dependencies and run with custom parameters"
53+
@echo " clean - Remove bundle artifacts"
54+
@echo " help - Show this help message"
55+
@echo ""
56+
@echo "Default parameters:"
57+
@echo " BUCKET_NAME = $(BUCKET_NAME)"
58+
@echo " OBJECT_KEY = $(OBJECT_KEY)"
59+
@echo " KMS_KEY_ID = $(KMS_KEY_ID)"
60+
@echo " AWS_REGION = $(AWS_REGION)"
61+
@echo ""
62+
@echo "To run with custom parameters:"
63+
@echo " make run BUCKET_NAME=your-bucket OBJECT_KEY=your-key KMS_KEY_ID=your-kms-key AWS_REGION=your-region"
64+
@echo ""
65+
@echo "Prerequisites:"
66+
@echo " - Ruby 3.0+ installed on the system"
67+
@echo " - Bundler gem installed (gem install bundler)"
68+
@echo " - AWS credentials configured (AWS CLI, environment variables, or IAM role)"
69+
@echo " - Valid S3 bucket and KMS key with appropriate permissions"
70+
@echo " - S3 Encryption Client v2 Ruby SDK (included in local-ruby-sdk)"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../test-server/ruby-v2-server/local-ruby-sdk

all-examples/ruby/v2/main.rb

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'aws-sdk-s3'
4+
require 'aws-sdk-kms'
5+
require 'json'
6+
7+
def main
8+
# Check command line arguments
9+
if ARGV.length != 4
10+
puts "Usage: #{$0} <bucket-name> <object-key> <kms-key-id> <region>"
11+
puts "Example: #{$0} avp-21638 s3ec-ruby-v2 arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01 us-east-2"
12+
exit 1
13+
end
14+
15+
bucket_name = ARGV[0]
16+
object_key = ARGV[1]
17+
kms_key_id = ARGV[2]
18+
region = ARGV[3]
19+
20+
puts "=== S3 Encryption Client v2 Example (Ruby) ==="
21+
puts "Bucket: #{bucket_name}"
22+
puts "Object Key: #{object_key}"
23+
puts "KMS Key ID: #{kms_key_id}"
24+
puts "Region: #{region}"
25+
puts
26+
27+
begin
28+
# Test data for encryption
29+
test_data = "Hello, World! This is a test message for S3 encryption client v2 in Ruby."
30+
puts "Original data: #{test_data}"
31+
puts "Data length: #{test_data.length} bytes"
32+
puts
33+
34+
puts "--- Initialize S3 Encryption Client v2 ---"
35+
36+
# Create regular S3 client
37+
s3_client = Aws::S3::Client.new(region: region)
38+
39+
# Create KMS client
40+
kms_client = Aws::KMS::Client.new(region: region)
41+
42+
# Create S3 Encryption Client v2
43+
encryption_client = Aws::S3::EncryptionV2::Client.new(
44+
client: s3_client,
45+
kms_key_id: kms_key_id,
46+
kms_client: kms_client,
47+
key_wrap_schema: :kms_context,
48+
content_encryption_schema: :aes_gcm_no_padding,
49+
security_profile: :v2
50+
)
51+
52+
puts "Successfully initialized S3 Encryption Client v2"
53+
puts "--- Encrypt and Upload Object to S3 ---"
54+
55+
# Add encryption context
56+
encryption_context = {
57+
'purpose' => 'example',
58+
'version' => 'v2',
59+
'language' => 'ruby'
60+
}
61+
62+
# Upload encrypted object using S3 Encryption Client
63+
put_response = encryption_client.put_object({
64+
bucket: bucket_name,
65+
key: object_key,
66+
body: test_data,
67+
kms_encryption_context: encryption_context
68+
})
69+
70+
puts "Successfully uploaded encrypted object to S3!"
71+
puts " Bucket: #{bucket_name}"
72+
puts " Key: #{object_key}"
73+
puts " Encryption Context: #{encryption_context}"
74+
puts
75+
76+
puts "--- Download and Decrypt Object from S3 ---"
77+
78+
# Download and decrypt object using S3 Encryption Client
79+
get_response = encryption_client.get_object({
80+
bucket: bucket_name,
81+
key: object_key,
82+
kms_encryption_context: encryption_context
83+
})
84+
85+
# Read the decrypted data
86+
decrypted_data = get_response.body.read
87+
88+
puts "Successfully downloaded and decrypted object from S3!"
89+
puts " Object size: #{decrypted_data.length} bytes"
90+
puts " Decrypted data: #{decrypted_data}"
91+
puts
92+
93+
puts "--- Verify Roundtrip Success ---"
94+
95+
# Verify the roundtrip was successful
96+
if decrypted_data == test_data
97+
puts "SUCCESS: Roundtrip encryption/decryption completed successfully!"
98+
puts " Original data matches decrypted data"
99+
puts " Data integrity verified"
100+
else
101+
puts "ERROR: Roundtrip failed - data mismatch"
102+
puts " Original: #{test_data}"
103+
puts " Decrypted: #{decrypted_data}"
104+
exit 1
105+
end
106+
107+
# Optionally Delete the Object
108+
#puts "--- Cleanup ---"
109+
# Clean up the test object using regular S3 client
110+
# s3_client.delete_object({
111+
# bucket: bucket_name,
112+
# key: object_key
113+
# })
114+
# puts "Test object deleted from S3"
115+
116+
puts
117+
puts "=== Example completed successfully! ==="
118+
119+
rescue Aws::S3::Errors::NoSuchBucket => e
120+
puts "Error: S3 bucket '#{bucket_name}' does not exist or is not accessible"
121+
puts " #{e.message}"
122+
exit 1
123+
rescue Aws::KMS::Errors::NotFoundException => e
124+
puts "Error: KMS key '#{kms_key_id}' not found or not accessible"
125+
puts " #{e.message}"
126+
exit 1
127+
rescue Aws::S3::EncryptionV2::Errors::EncryptionError => e
128+
puts "S3 Encryption Error: #{e.message}"
129+
exit 1
130+
rescue Aws::S3::EncryptionV2::Errors::DecryptionError => e
131+
puts "S3 Decryption Error: #{e.message}"
132+
exit 1
133+
rescue Aws::Errors::ServiceError => e
134+
puts "AWS Service Error: #{e.message}"
135+
puts " Error Code: #{e.code}" if e.respond_to?(:code)
136+
exit 1
137+
rescue StandardError => e
138+
puts "Unexpected error: #{e.message}"
139+
puts e.backtrace.first(5)
140+
exit 1
141+
end
142+
end
143+
144+
# Run the main function if this script is executed directly
145+
if __FILE__ == $0
146+
main
147+
end

0 commit comments

Comments
 (0)