main/searchableencryption/
beacon_styles_searchable_encryption.rs1use crate::test_utils;
5use aws_db_esdk::dynamodb::types::BeaconKeySource;
6use aws_db_esdk::dynamodb::types::BeaconStyle;
7use aws_db_esdk::dynamodb::types::BeaconVersion;
8use aws_db_esdk::dynamodb::types::CompoundBeacon;
9use aws_db_esdk::dynamodb::types::DynamoDbTableEncryptionConfig;
10use aws_db_esdk::dynamodb::types::EncryptedPart;
11use aws_db_esdk::dynamodb::types::SearchConfig;
12use aws_db_esdk::dynamodb::types::SingleKeyStore;
13use aws_db_esdk::dynamodb::types::StandardBeacon;
14use aws_db_esdk::dynamodb::types::*;
15use aws_db_esdk::intercept::DbEsdkInterceptor;
16use aws_db_esdk::key_store::client as keystore_client;
17use aws_db_esdk::key_store::types::key_store_config::KeyStoreConfig;
18use aws_db_esdk::key_store::types::KmsConfiguration;
19use aws_db_esdk::material_providers::client as mpl_client;
20use aws_db_esdk::material_providers::types::material_providers_config::MaterialProvidersConfig;
21use aws_db_esdk::CryptoAction;
22use aws_db_esdk::DynamoDbTablesEncryptionConfig;
23use aws_sdk_dynamodb::types::AttributeValue;
24use std::collections::HashMap;
25
26pub async fn put_and_query_with_beacon(branch_key_id: &str) -> Result<(), crate::BoxError> {
57 let ddb_table_name = test_utils::UNIT_INSPECTION_TEST_DDB_TABLE_NAME;
58 let branch_key_wrapping_kms_key_arn = test_utils::TEST_BRANCH_KEY_WRAPPING_KMS_KEY_ARN;
59 let branch_key_ddb_table_name = test_utils::TEST_BRANCH_KEYSTORE_DDB_TABLE_NAME;
60
61 let standard_beacon_list = vec![
63 StandardBeacon::builder().name("fruit").length(30).build()?,
68 StandardBeacon::builder()
74 .name("basket")
75 .length(30)
76 .style(BeaconStyle::SharedSet(
77 SharedSet::builder().other("fruit").build()?,
78 ))
79 .build()?,
80 StandardBeacon::builder()
84 .name("dessert")
85 .length(30)
86 .style(BeaconStyle::Shared(
87 Shared::builder().other("fruit").build()?,
88 ))
89 .build()?,
90 StandardBeacon::builder()
93 .name("veggies")
94 .length(30)
95 .style(BeaconStyle::AsSet(AsSet::builder().build()?))
96 .build()?,
97 StandardBeacon::builder()
101 .name("work_type")
102 .length(30)
103 .style(BeaconStyle::PartOnly(PartOnly::builder().build()?))
104 .build()?,
105 ];
106
107 let encrypted_part_list = vec![EncryptedPart::builder()
111 .name("work_type")
112 .prefix("T-")
113 .build()?];
114
115 let signed_part_list = vec![SignedPart::builder().name("work_id").prefix("I-").build()?];
116
117 let compound_beacon_list = vec![CompoundBeacon::builder()
118 .name("work_unit")
119 .split(".")
120 .encrypted(encrypted_part_list)
121 .signed(signed_part_list)
122 .build()?];
123
124 let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
127 let key_store_config = KeyStoreConfig::builder()
128 .kms_client(aws_sdk_kms::Client::new(&sdk_config))
129 .ddb_client(aws_sdk_dynamodb::Client::new(&sdk_config))
130 .ddb_table_name(branch_key_ddb_table_name)
131 .logical_key_store_name(branch_key_ddb_table_name)
132 .kms_configuration(KmsConfiguration::KmsKeyArn(
133 branch_key_wrapping_kms_key_arn.to_string(),
134 ))
135 .build()?;
136
137 let key_store = keystore_client::Client::from_conf(key_store_config)?;
138
139 let beacon_version = BeaconVersion::builder()
142 .standard_beacons(standard_beacon_list)
143 .compound_beacons(compound_beacon_list)
144 .version(1) .key_store(key_store.clone())
146 .key_source(BeaconKeySource::Single(
147 SingleKeyStore::builder()
148 .key_id(branch_key_id)
154 .cache_ttl(6000)
155 .build()?,
156 ))
157 .build()?;
158 let beacon_versions = vec![beacon_version];
159
160 let mpl_config = MaterialProvidersConfig::builder().build()?;
163 let mpl = mpl_client::Client::from_conf(mpl_config)?;
164 let kms_keyring = mpl
165 .create_aws_kms_hierarchical_keyring()
166 .branch_key_id(branch_key_id)
167 .key_store(key_store)
168 .ttl_seconds(6000)
169 .send()
170 .await?;
171
172 let attribute_actions_on_encrypt = HashMap::from([
174 ("work_id".to_string(), CryptoAction::SignOnly), ("inspection_date".to_string(), CryptoAction::SignOnly), ("dessert".to_string(), CryptoAction::EncryptAndSign), ("fruit".to_string(), CryptoAction::EncryptAndSign), ("basket".to_string(), CryptoAction::EncryptAndSign), ("veggies".to_string(), CryptoAction::EncryptAndSign), ("work_type".to_string(), CryptoAction::EncryptAndSign), ]);
182
183 let table_config = DynamoDbTableEncryptionConfig::builder()
186 .logical_table_name(ddb_table_name)
187 .partition_key_name("work_id")
188 .sort_key_name("inspection_date")
189 .attribute_actions_on_encrypt(attribute_actions_on_encrypt)
190 .keyring(kms_keyring)
191 .search(
192 SearchConfig::builder()
193 .write_version(1) .versions(beacon_versions)
195 .build()?,
196 )
197 .build()?;
198
199 let encryption_config = DynamoDbTablesEncryptionConfig::builder()
201 .table_encryption_configs(HashMap::from([(ddb_table_name.to_string(), table_config)]))
202 .build()?;
203
204 let item1 = HashMap::from([
206 ("work_id".to_string(), AttributeValue::S("1".to_string())),
207 (
208 "inspection_date".to_string(),
209 AttributeValue::S("2023-06-13".to_string()),
210 ),
211 ("dessert".to_string(), AttributeValue::S("cake".to_string())),
212 ("fruit".to_string(), AttributeValue::S("banana".to_string())),
213 (
214 "basket".to_string(),
215 AttributeValue::Ss(vec![
216 "banana".to_string(),
217 "apple".to_string(),
218 "pear".to_string(),
219 ]),
220 ),
221 (
222 "veggies".to_string(),
223 AttributeValue::Ss(vec![
224 "beans".to_string(),
225 "carrots".to_string(),
226 "celery".to_string(),
227 ]),
228 ),
229 (
230 "work_type".to_string(),
231 AttributeValue::S("small".to_string()),
232 ),
233 ]);
234
235 let item2 = HashMap::from([
237 ("work_id".to_string(), AttributeValue::S("2".to_string())),
238 (
239 "inspection_date".to_string(),
240 AttributeValue::S("2023-06-13".to_string()),
241 ),
242 (
243 "dessert".to_string(),
244 AttributeValue::S("orange".to_string()),
245 ),
246 ("fruit".to_string(), AttributeValue::S("orange".to_string())),
247 (
248 "basket".to_string(),
249 AttributeValue::Ss(vec![
250 "strawberry".to_string(),
251 "blueberry".to_string(),
252 "blackberry".to_string(),
253 ]),
254 ),
255 (
256 "veggies".to_string(),
257 AttributeValue::Ss(vec![
258 "beans".to_string(),
259 "carrots".to_string(),
260 "peas".to_string(),
261 ]),
262 ),
263 (
264 "work_type".to_string(),
265 AttributeValue::S("large".to_string()),
266 ),
267 ]);
268
269 let dynamo_config = aws_sdk_dynamodb::config::Builder::from(&sdk_config)
271 .interceptor(DbEsdkInterceptor::new(encryption_config)?)
272 .build();
273 let ddb = aws_sdk_dynamodb::Client::from_conf(dynamo_config);
274
275 ddb.put_item()
277 .table_name(ddb_table_name)
278 .set_item(Some(item1.clone()))
279 .send()
280 .await?;
281
282 ddb.put_item()
283 .table_name(ddb_table_name)
284 .set_item(Some(item2.clone()))
285 .send()
286 .await?;
287
288 let expression_attribute_values = HashMap::from([(
291 ":value".to_string(),
292 AttributeValue::S("banana".to_string()),
293 )]);
294
295 let scan_response = ddb
296 .scan()
297 .table_name(ddb_table_name)
298 .filter_expression("contains(basket, :value)")
299 .set_expression_attribute_values(Some(expression_attribute_values.clone()))
300 .send()
301 .await?;
302
303 let attribute_values = scan_response.items.unwrap();
304 assert_eq!(attribute_values.len(), 1);
306 let returned_item = &attribute_values[0];
307 assert_eq!(returned_item["work_id"], item1["work_id"]);
309
310 let scan_response = ddb
313 .scan()
314 .table_name(ddb_table_name)
315 .filter_expression("contains(basket, fruit)")
316 .send()
317 .await?;
318
319 let attribute_values = scan_response.items.unwrap();
320 assert_eq!(attribute_values.len(), 1);
322 let returned_item = &attribute_values[0];
323 assert_eq!(returned_item["work_id"], item1["work_id"]);
325
326 let basket3 = vec![
329 "boysenberry".to_string(),
330 "orange".to_string(),
331 "grape".to_string(),
332 ];
333 let expression_attribute_values =
334 HashMap::from([(":value".to_string(), AttributeValue::Ss(basket3))]);
335
336 let scan_response = ddb
337 .scan()
338 .table_name(ddb_table_name)
339 .filter_expression("contains(:value, fruit)")
340 .set_expression_attribute_values(Some(expression_attribute_values.clone()))
341 .send()
342 .await?;
343
344 let attribute_values = scan_response.items.unwrap();
345 assert_eq!(attribute_values.len(), 1);
347 let returned_item = &attribute_values[0];
348 assert_eq!(returned_item["work_id"], item2["work_id"]);
350
351 let scan_response = ddb
353 .scan()
354 .table_name(ddb_table_name)
355 .filter_expression("dessert = fruit")
356 .send()
357 .await?;
358
359 let attribute_values = scan_response.items.unwrap();
360 assert_eq!(attribute_values.len(), 1);
362 let returned_item = &attribute_values[0];
363 assert_eq!(returned_item["work_id"], item2["work_id"]);
365
366 let expression_attribute_values =
369 HashMap::from([(":value".to_string(), AttributeValue::S("peas".to_string()))]);
370
371 let scan_response = ddb
372 .scan()
373 .table_name(ddb_table_name)
374 .filter_expression("contains(veggies, :value)")
375 .set_expression_attribute_values(Some(expression_attribute_values.clone()))
376 .send()
377 .await?;
378
379 let attribute_values = scan_response.items.unwrap();
380 assert_eq!(attribute_values.len(), 1);
382 let returned_item = &attribute_values[0];
383 assert_eq!(returned_item["work_id"], item2["work_id"]);
385
386 let expression_attribute_values = HashMap::from([(
388 ":value".to_string(),
389 AttributeValue::S("I-1.T-small".to_string()),
390 )]);
391
392 let scan_response = ddb
393 .scan()
394 .table_name(ddb_table_name)
395 .filter_expression("work_unit = :value")
396 .set_expression_attribute_values(Some(expression_attribute_values.clone()))
397 .send()
398 .await?;
399
400 let attribute_values = scan_response.items.unwrap();
401 assert_eq!(attribute_values.len(), 1);
403 let returned_item = &attribute_values[0];
404 assert_eq!(returned_item["work_id"], item1["work_id"]);
406
407 println!("beacon_styles_searchable_encryption successful.");
408 Ok(())
409}