Skip to content

Commit a7c313f

Browse files
committed
m
1 parent 7933a2c commit a7c313f

File tree

2 files changed

+199
-7
lines changed

2 files changed

+199
-7
lines changed

DynamoDbEncryption/runtimes/rust/src/bin/example/main.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,23 @@ pub mod itemencryptor;
1111
pub mod searchableencryption;
1212
pub mod create_keystore_key;
1313
pub mod get_encrypted_data_key_description;
14+
pub mod multi_get_put_example;
1415

1516
#[tokio::main]
1617
pub async fn main() {
1718
basic_get_put_example::put_item_get_item().await;
1819
itemencryptor::item_encrypt_decrypt::encrypt_decrypt().await;
1920
get_encrypted_data_key_description::get_encrypted_data_key_description().await;
21+
multi_get_put_example::multi_put_get().await;
2022

21-
let key_id = create_keystore_key::keystore_create_key().await;
22-
// let key_id2 = create_keystore_key::keystore_create_key().await;
23-
// Key creation is eventually consistent, so wait 5 seconds to decrease the likelihood
24-
// our test fails due to eventual consistency issues.
25-
std::thread::sleep(std::time::Duration::from_secs(5));
23+
// let key_id = create_keystore_key::keystore_create_key().await;
24+
// // let key_id2 = create_keystore_key::keystore_create_key().await;
25+
// // Key creation is eventually consistent, so wait 5 seconds to decrease the likelihood
26+
// // our test fails due to eventual consistency issues.
27+
// std::thread::sleep(std::time::Duration::from_secs(5));
2628

27-
searchableencryption::basic_searchable_encryption::put_and_query_with_beacon(&key_id).await;
28-
// FIXME : ScanError will have to wait until we have a reasonable error message strategy
29+
// searchableencryption::basic_searchable_encryption::put_and_query_with_beacon(&key_id).await;
30+
// // FIXME : ScanError will have to wait until we have a reasonable error message strategy
2931

3032
/*
3133
await MultiPutGetExample.MultiPutGet();
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use std::collections::HashMap;
5+
use crate::test_utils;
6+
use aws_sdk_dynamodb::types::AttributeValue;
7+
8+
use db_esdk::aws_cryptography_materialProviders::types::material_providers_config::MaterialProvidersConfig;
9+
use db_esdk::aws_cryptography_materialProviders::client;
10+
use db_esdk::aws_cryptography_dbEncryptionSdk_structuredEncryption::types::CryptoAction;
11+
12+
use db_esdk::aws_cryptography_dbEncryptionSdk_dynamoDb::types::DynamoDbTableEncryptionConfig;
13+
use db_esdk::aws_cryptography_materialProviders::types::DbeAlgorithmSuiteId;
14+
use db_esdk::intercept::DbEsdkInterceptor;
15+
use db_esdk::types::dynamo_db_tables_encryption_config::DynamoDbTablesEncryptionConfig;
16+
17+
/*
18+
This example sets up DynamoDb Encryption for the AWS SDK client
19+
and uses the low level PutItem and GetItem DDB APIs to demonstrate
20+
putting a client-side encrypted item into DynamoDb
21+
and then retrieving and decrypting that item from DynamoDb.
22+
23+
Running this example requires access to the DDB Table whose name
24+
is provided in CLI arguments.
25+
This table must be configured with the following
26+
primary key configuration:
27+
- Partition key is named "partition_key" with type (S)
28+
- Sort key is named "sort_key" with type (N)
29+
*/
30+
31+
pub async fn multi_put_get()
32+
{
33+
let kms_key_id = test_utils::TEST_KMS_KEY_ID;
34+
let ddb_table_name = test_utils::TEST_DDB_TABLE_NAME;
35+
36+
// 1. Create a Keyring. This Keyring will be responsible for protecting the data keys that protect your data.
37+
// For this example, we will create a AWS KMS Keyring with the AWS KMS Key we want to use.
38+
// We will use the `CreateMrkMultiKeyring` method to create this keyring,
39+
// as it will correctly handle both single region and Multi-Region KMS Keys.
40+
let provider_config = MaterialProvidersConfig::builder().build().unwrap();
41+
let mat_prov = client::Client::from_conf(provider_config).unwrap();
42+
let kms_keyring = mat_prov.create_aws_kms_mrk_multi_keyring().generator(kms_key_id).send().await.unwrap();
43+
44+
// 2. Configure which attributes are encrypted and/or signed when writing new items.
45+
// For each attribute that may exist on the items we plan to write to our DynamoDbTable,
46+
// we must explicitly configure how they should be treated during item encryption:
47+
// - ENCRYPT_AND_SIGN: The attribute is encrypted and included in the signature
48+
// - SIGN_ONLY: The attribute not encrypted, but is still included in the signature
49+
// - DO_NOTHING: The attribute is not encrypted and not included in the signature
50+
let attribute_actions_on_encrypt = HashMap::from([
51+
("partition_key".to_string(), CryptoAction::SignOnly),
52+
("sort_key".to_string(), CryptoAction::SignOnly),
53+
("attribute1".to_string(), CryptoAction::EncryptAndSign),
54+
("attribute2".to_string(), CryptoAction::SignOnly),
55+
(":attribute3".to_string(), CryptoAction::DoNothing),
56+
]);
57+
58+
// 3. Configure which attributes we expect to be included in the signature
59+
// when reading items. There are two options for configuring this:
60+
//
61+
// - (Recommended) Configure `allowedUnsignedAttributesPrefix`:
62+
// When defining your DynamoDb schema and deciding on attribute names,
63+
// choose a distinguishing prefix (such as ":") for all attributes that
64+
// you do not want to include in the signature.
65+
// This has two main benefits:
66+
// - It is easier to reason about the security and authenticity of data within your item
67+
// when all unauthenticated data is easily distinguishable by their attribute name.
68+
// - If you need to add new unauthenticated attributes in the future,
69+
// you can easily make the corresponding update to your `attributeActionsOnEncrypt`
70+
// and immediately start writing to that new attribute, without
71+
// any other configuration update needed.
72+
// Once you configure this field, it is not safe to update it.
73+
//
74+
// - Configure `allowedUnsignedAttributes`: You may also explicitly list
75+
// a set of attributes that should be considered unauthenticated when encountered
76+
// on read. Be careful if you use this configuration. Do not remove an attribute
77+
// name from this configuration, even if you are no longer writing with that attribute,
78+
// as old items may still include this attribute, and our configuration needs to know
79+
// to continue to exclude this attribute from the signature scope.
80+
// If you add new attribute names to this field, you must first deploy the update to this
81+
// field to all readers in your host fleet before deploying the update to start writing
82+
// with that new attribute.
83+
//
84+
// For this example, we have designed our DynamoDb table such that any attribute name with
85+
// the ":" prefix should be considered unauthenticated.
86+
const UNSIGNED_ATTR_PREFIX : &str = ":";
87+
88+
// 4. Create the DynamoDb Encryption configuration for the table we will be writing to.
89+
let table_config = DynamoDbTableEncryptionConfig::builder()
90+
.logical_table_name(ddb_table_name)
91+
.partition_key_name("partition_key")
92+
.sort_key_name("sort_key")
93+
.attribute_actions_on_encrypt(attribute_actions_on_encrypt)
94+
.keyring(kms_keyring)
95+
.allowed_unsigned_attribute_prefix(UNSIGNED_ATTR_PREFIX)
96+
// Specifying an algorithm suite is not required,
97+
// but is done here to demonstrate how to do so.
98+
// We suggest using the
99+
// `ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384_SYMSIG_HMAC_SHA384` suite,
100+
// which includes AES-GCM with key derivation, signing, and key commitment.
101+
// This is also the default algorithm suite if one is not specified in this config.
102+
// For more information on supported algorithm suites, see:
103+
// https://docs.aws.amazon.com/database-encryption-sdk/latest/devguide/supported-algorithms.html
104+
.algorithm_suite_id(DbeAlgorithmSuiteId::AlgAes256GcmHkdfSha512CommitKeyEcdsaP384SymsigHmacSha384)
105+
.build().unwrap();
106+
107+
let table_configs = DynamoDbTablesEncryptionConfig::builder()
108+
.table_encryption_configs(HashMap::from([(ddb_table_name.to_string(), table_config)]))
109+
.build()
110+
.unwrap();
111+
112+
// 5. Create a new AWS SDK DynamoDb client using the TableEncryptionConfigs
113+
let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
114+
let dynamo_config = aws_sdk_dynamodb::config::Builder::from(&sdk_config)
115+
.interceptor(DbEsdkInterceptor::new(table_configs))
116+
.build();
117+
let ddb = aws_sdk_dynamodb::Client::from_conf(dynamo_config);
118+
119+
// 6. Put an item into our table using the above client.
120+
// Before the item gets sent to DynamoDb, it will be encrypted
121+
// client-side, according to our configuration.
122+
let batch_write_item = HashMap::from([
123+
("partition_key".to_string(), AttributeValue::S("BatchWriteItemExample".to_string())),
124+
("sort_key".to_string(), AttributeValue::N("0".to_string())),
125+
("attribute1".to_string(), AttributeValue::S("encrypt and sign me!".to_string())),
126+
("attribute2".to_string(), AttributeValue::S("sign me!".to_string())),
127+
(":attribute3".to_string(), AttributeValue::S("ignore me!".to_string())),
128+
]);
129+
let put_request = aws_sdk_dynamodb::types::PutRequest::builder().set_item(Some(batch_write_item)).build().unwrap();
130+
let batch_write_request = aws_sdk_dynamodb::types::WriteRequest::builder().put_request(put_request).build();
131+
132+
let transact_write_item = HashMap::from([
133+
("partition_key".to_string(), AttributeValue::S("TransactWriteItemExample".to_string())),
134+
("sort_key".to_string(), AttributeValue::N("0".to_string())),
135+
("attribute1".to_string(), AttributeValue::S("encrypt and sign me!".to_string())),
136+
("attribute2".to_string(), AttributeValue::S("sign me!".to_string())),
137+
(":attribute3".to_string(), AttributeValue::S("ignore me!".to_string())),
138+
]);
139+
let transact_put = aws_sdk_dynamodb::types::Put::builder().table_name(ddb_table_name).set_item(Some(transact_write_item)).build().unwrap();
140+
let transact_item = aws_sdk_dynamodb::types::TransactWriteItem::builder().put(transact_put).build();
141+
142+
let _batch_write_response = ddb.batch_write_item()
143+
.request_items(ddb_table_name, vec![batch_write_request])
144+
.send().await.unwrap();
145+
146+
let _transact_write_response = ddb.transact_write_items()
147+
.transact_items(transact_item)
148+
.send().await.unwrap();
149+
150+
151+
// 7. Get the item back from our table using the same client.
152+
// The client will decrypt the item client-side, and return
153+
// back the original item.
154+
let batch_get_keys = HashMap::from([
155+
("partition_key".to_string(), AttributeValue::S("BatchWriteItemExample".to_string())),
156+
("sort_key".to_string(), AttributeValue::N("0".to_string())),
157+
]);
158+
let keys_and_attr = aws_sdk_dynamodb::types::KeysAndAttributes::builder()
159+
.keys(batch_get_keys)
160+
.consistent_read(true)
161+
.build().unwrap();
162+
163+
let batch_get_response = ddb
164+
.batch_get_item()
165+
.request_items(ddb_table_name, keys_and_attr)
166+
.send()
167+
.await
168+
.unwrap();
169+
170+
let returned_item = &batch_get_response.responses.unwrap()[ddb_table_name][0];
171+
assert_eq!(returned_item["attribute1"], AttributeValue::S("encrypt and sign me!".to_string()));
172+
173+
174+
let transact_get_keys = HashMap::from([
175+
("partition_key".to_string(), AttributeValue::S("TransactWriteItemExample".to_string())),
176+
("sort_key".to_string(), AttributeValue::N("0".to_string())),
177+
]);
178+
let transact_get = aws_sdk_dynamodb::types::Get::builder().table_name(ddb_table_name).set_key(Some(transact_get_keys)).build().unwrap();
179+
let transact_get_item = aws_sdk_dynamodb::types::TransactGetItem::builder().get(transact_get).build();
180+
let transact_get_response = ddb.transact_get_items()
181+
.transact_items(transact_get_item)
182+
.send()
183+
.await
184+
.unwrap();
185+
186+
let the_item = transact_get_response.responses.as_ref().unwrap()[0].item.as_ref().unwrap();
187+
assert_eq!(the_item["attribute1"], AttributeValue::S("encrypt and sign me!".to_string()));
188+
189+
println!("multi_put_get successful.");
190+
}

0 commit comments

Comments
 (0)