Skip to content

Commit 34cbbcf

Browse files
authored
c++ example (#79)
* c++ example
1 parent 64db72a commit 34cbbcf

6 files changed

Lines changed: 282 additions & 12 deletions

File tree

.github/workflows/examples.yml

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,14 @@ jobs:
1717
submodules: true
1818
token: ${{ secrets.PAT_FOR_PRIVATE_RUBY }}
1919

20-
- name: Checkout CPP code for cpp-v2-transition
20+
- name: Checkout CPP code cpp-examples
2121
uses: actions/checkout@v5
2222
with:
2323
submodules: recursive
2424
token: ${{ secrets.PAT_FOR_CPP }}
2525
repository: awslabs/aws-sdk-cpp-staging
2626
ref: fire-egg-dev
27-
path: test-server/cpp-v2-transition-server/aws-sdk-cpp/
28-
29-
- name: Checkout CPP code cpp-v3
30-
uses: actions/checkout@v5
31-
with:
32-
submodules: recursive
33-
token: ${{ secrets.PAT_FOR_CPP }}
34-
repository: awslabs/aws-sdk-cpp-staging
35-
ref: fire-egg-dev
36-
path: test-server/cpp-v3-server/aws-sdk-cpp/
27+
path: all-examples/cpp/aws-sdk-cpp/
3728

3829
- name: Checkout .NET V2 code
3930
uses: actions/checkout@v5

all-examples/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
.PHONY: all install clean run help list-examples
66

77
# Find all directories with Makefiles
8-
EXAMPLE_DIRS := $(shell find . -name Makefile -not -path "./Makefile" | xargs dirname | sed 's|^\./||' | $(if $(FILTER),grep -E "$$(echo '$(FILTER)' | sed 's/,/|/g')",cat) | sort)
8+
EXAMPLE_DIRS := $(shell find . -name Makefile -not -path "./Makefile" -not -path "./cpp/aws-sdk-cpp/**" -not -path "./cpp/build/**" | xargs dirname | sed 's|^\./||' | $(if $(FILTER),grep -E "$$(echo '$(FILTER)' | sed 's/,/|/g')",cat) | sort)
99

1010
all: install
1111

all-examples/cpp/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
project(s3ec-test)
3+
4+
set(CMAKE_CXX_STANDARD 14)
5+
6+
# Configure AWS SDK build options
7+
set(BUILD_ONLY "kms;s3;s3-encryption" CACHE STRING "Build only KMS, S3, and S3-encryption components")
8+
set(ENABLE_TESTING OFF CACHE BOOL "Disable testing")
9+
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build static libraries")
10+
11+
# Add AWS SDK as subdirectory
12+
add_subdirectory(aws-sdk-cpp)
13+
14+
find_package(PkgConfig REQUIRED)
15+
16+
add_executable(s3ec-test main.cpp)
17+
18+
target_link_libraries(s3ec-test
19+
aws-cpp-sdk-core
20+
aws-cpp-sdk-kms
21+
aws-cpp-sdk-s3
22+
aws-cpp-sdk-s3-encryption
23+
)

all-examples/cpp/Makefile

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Makefile for S3 Encryption Client C++ Example
2+
3+
.PHONY: all install clean run help
4+
5+
# Default arguments for running the example
6+
# Override these when calling make run
7+
VERSION ?= V3
8+
BUCKET_NAME ?= avp-21638
9+
OBJECT_KEY ?= s3ec-cpp-test
10+
KMS_KEY_ID ?= arn:aws:kms:us-east-2:648638458147:key/a47079da-17e4-45a5-b82e-2bac101cad01
11+
AWS_REGION ?= us-east-2
12+
13+
all: run
14+
15+
install: build/s3ec-test
16+
17+
aws-sdk-cpp:
18+
git clone --recurse-submodules -b fire-egg-dev https://github.com/awslabs/aws-sdk-cpp-staging.git aws-sdk-cpp
19+
20+
build/s3ec-test: aws-sdk-cpp
21+
mkdir -p build && cd build && cmake .. && make
22+
23+
clean:
24+
rm -rf build
25+
26+
# Run the example with default arguments
27+
run: build/s3ec-test
28+
@echo "Running S3 Encryption Client C++ example..."
29+
@echo "Version: $(VERSION)"
30+
@echo "Bucket: $(BUCKET_NAME)"
31+
@echo "Object Key: $(OBJECT_KEY)"
32+
@echo "KMS Key ID: $(KMS_KEY_ID)"
33+
@echo "Region: $(AWS_REGION)"
34+
@echo ""
35+
./build/s3ec-test $(VERSION) $(BUCKET_NAME) $(OBJECT_KEY) $(KMS_KEY_ID) $(AWS_REGION)
36+
37+
# Show help
38+
help:
39+
@echo "S3 Encryption Client C++ Example Makefile"
40+
@echo ""
41+
@echo "Available targets:"
42+
@echo " install - Install Go dependencies using Go modules"
43+
@echo " run - Install dependencies and run the example"
44+
@echo " clean - Remove C++ artifacts"
45+
@echo " help - Show this help message"
46+
@echo ""
47+
@echo "Default parameters:"
48+
@echo " VERSION = $(VERSION) (must be V2 or V3)"
49+
@echo " BUCKET_NAME = $(BUCKET_NAME)"
50+
@echo " OBJECT_KEY = $(OBJECT_KEY)"
51+
@echo " KMS_KEY_ID = $(KMS_KEY_ID)"
52+
@echo " AWS_REGION = $(AWS_REGION)"
53+
@echo ""
54+
@echo "To run with custom parameters:"
55+
@echo " make run VERSION=your-version BUCKET_NAME=your-bucket OBJECT_KEY=your-key KMS_KEY_ID=your-kms-key AWS_REGION=your-region"
56+
@echo ""
57+
@echo "Prerequisites:"
58+
@echo " - Read access to https://github.com/awslabs/aws-sdk-cpp-staging.git"
59+
@echo " - AWS credentials configured (AWS CLI, environment variables, or IAM role)"
60+
@echo " - Valid S3 bucket and KMS key with appropriate permissions"

all-examples/cpp/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# C++ S3 Encryption Test
2+
3+
Minimal C++ use of S3 Encryption
4+
5+
## Build
6+
7+
```bash
8+
make install
9+
```
10+
11+
## Run
12+
13+
```bash
14+
make run
15+
```

all-examples/cpp/main.cpp

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#include <aws/core/Aws.h>
2+
#include <aws/kms/KMSClient.h>
3+
#include <aws/s3-encryption/CryptoConfiguration.h>
4+
#include <aws/s3-encryption/S3EncryptionClient.h>
5+
#include <aws/s3-encryption/materials/KMSEncryptionMaterials.h>
6+
#include <aws/s3/model/GetObjectRequest.h>
7+
#include <aws/s3/model/PutObjectRequest.h>
8+
#include <aws/core/client/ClientConfiguration.h>
9+
10+
#include <memory>
11+
#include <string>
12+
#include <unordered_map>
13+
14+
using namespace Aws::S3Encryption;
15+
using Aws::S3Encryption::Materials::KMSWithContextEncryptionMaterials;
16+
17+
static Aws::Map<Aws::String, Aws::String> get_encryption_context(const char * version)
18+
{
19+
return {
20+
{"purpose", "example"},
21+
{"version", version},
22+
{"language", "c++"}
23+
};
24+
}
25+
26+
static int test_v3(const char *bucket, const char *object, const char *kms_key_id, const char *region)
27+
{
28+
Aws::Client::ClientConfiguration s3ClientConfig;
29+
s3ClientConfig.region = region;
30+
31+
auto materials = std::make_shared<KMSWithContextEncryptionMaterials>(kms_key_id, s3ClientConfig);
32+
CryptoConfigurationV3 config(materials);
33+
// config.AllowLegacy();
34+
// config.SetStorageMethod(StorageMethod::INSTRUCTION_FILE);
35+
// config.SetCommitmentPolicy(CommitmentPolicy::FORBID_ENCRYPT_ALLOW_DECRYPT);
36+
37+
38+
auto client = std::make_shared<S3EncryptionClientV3>(config, s3ClientConfig);
39+
40+
auto encryption_context = get_encryption_context("V3");
41+
42+
Aws::S3::Model::PutObjectRequest put_request;
43+
put_request.SetBucket(bucket);
44+
put_request.SetKey(object);
45+
46+
auto data = std::string("This is the sample content.");
47+
48+
auto stream = std::make_shared<std::stringstream>(data);
49+
put_request.SetBody(stream);
50+
51+
auto put_outcome = client->PutObject(put_request, encryption_context);
52+
if (put_outcome.IsSuccess())
53+
{
54+
fprintf(stderr, "PutObject V3 Successful.\n");
55+
}
56+
else
57+
{
58+
fprintf(stderr, "PutObject V3 Failed : %s\n", put_outcome.GetError().GetMessage().c_str());
59+
return 1;
60+
}
61+
62+
Aws::S3::Model::GetObjectRequest get_request;
63+
get_request.SetBucket(bucket);
64+
get_request.SetKey(object);
65+
auto get_outcome = client->GetObject(get_request, encryption_context);
66+
if (get_outcome.IsSuccess())
67+
{
68+
fprintf(stderr, "GetObject V3 Successful.\n");
69+
Aws::StringStream response_stream;
70+
response_stream << get_outcome.GetResult().GetBody().rdbuf();
71+
if (response_stream.str() != data)
72+
{
73+
fprintf(stderr, "GetObject V3 returned the wrong data.\n");
74+
return 1;
75+
}
76+
}
77+
else
78+
{
79+
fprintf(stderr, "GetObject V3 Failed : %s\n", put_outcome.GetError().GetMessage().c_str());
80+
return 1;
81+
}
82+
return 0;
83+
}
84+
85+
static int test_v2(const char *bucket, const char *object, const char *kms_key_id, const char *region)
86+
{
87+
Aws::Client::ClientConfiguration s3ClientConfig;
88+
s3ClientConfig.region = region;
89+
90+
auto materials = std::make_shared<KMSWithContextEncryptionMaterials>(kms_key_id, s3ClientConfig);
91+
CryptoConfigurationV2 config(materials);
92+
// config.SetSecurityProfile(SecurityProfile::V2_AND_LEGACY);
93+
// config.SetStorageMethod(StorageMethod::INSTRUCTION_FILE);
94+
95+
96+
auto client = std::make_shared<S3EncryptionClientV2>(config, s3ClientConfig);
97+
98+
auto encryption_context = get_encryption_context("V2");
99+
100+
Aws::S3::Model::PutObjectRequest put_request;
101+
put_request.SetBucket(bucket);
102+
put_request.SetKey(object);
103+
104+
auto data = std::string("This is the sample content.");
105+
106+
auto stream = std::make_shared<std::stringstream>(data);
107+
put_request.SetBody(stream);
108+
109+
auto put_outcome = client->PutObject(put_request, encryption_context);
110+
if (put_outcome.IsSuccess())
111+
{
112+
fprintf(stderr, "PutObject V2 Successful.\n");
113+
}
114+
else
115+
{
116+
fprintf(stderr, "PutObject V2 Failed : %s\n", put_outcome.GetError().GetMessage().c_str());
117+
return 1;
118+
}
119+
120+
Aws::S3::Model::GetObjectRequest get_request;
121+
get_request.SetBucket(bucket);
122+
get_request.SetKey(object);
123+
auto get_outcome = client->GetObject(get_request, encryption_context);
124+
if (get_outcome.IsSuccess())
125+
{
126+
fprintf(stderr, "GetObject V2 Successful.\n");
127+
Aws::StringStream response_stream;
128+
response_stream << get_outcome.GetResult().GetBody().rdbuf();
129+
if (response_stream.str() != data)
130+
{
131+
fprintf(stderr, "GetObject V2 returned the wrong data.\n");
132+
return 1;
133+
}
134+
}
135+
else
136+
{
137+
fprintf(stderr, "GetObject V2 Failed : %s\n", put_outcome.GetError().GetMessage().c_str());
138+
return 1;
139+
}
140+
return 0;
141+
}
142+
143+
int main(int argc, char **argv)
144+
{
145+
if (argc != 6)
146+
{
147+
fprintf(stderr, "USAGE : s3ec-test version bucket object key_id region");
148+
return 1;
149+
}
150+
151+
auto version_str = argv[1];
152+
auto bucket = argv[2];
153+
auto object = argv[3];
154+
auto kms_key_id = argv[4];
155+
auto region = argv[5];
156+
157+
bool is_v3;
158+
if (strcasecmp(version_str, "v3") == 0)
159+
{
160+
is_v3 = true;
161+
}
162+
else if (strcasecmp(version_str, "v2") == 0)
163+
{
164+
is_v3 = false;
165+
}
166+
else
167+
{
168+
fprintf(stderr, "Version was <%s> must be V2 or V3\n", version_str);
169+
return 1;
170+
}
171+
172+
Aws::SDKOptions options;
173+
Aws::InitAPI(options);
174+
175+
if (is_v3)
176+
test_v3(bucket, object, kms_key_id, region);
177+
else
178+
test_v2(bucket, object, kms_key_id, region);
179+
180+
Aws::ShutdownAPI(options);
181+
}

0 commit comments

Comments
 (0)