main/searchableencryption/complexexample/
beacon_config.rs1use aws_db_esdk::dynamodb::types::BeaconKeySource;
5use aws_db_esdk::dynamodb::types::BeaconVersion;
6use aws_db_esdk::dynamodb::types::CompoundBeacon;
7use aws_db_esdk::dynamodb::types::Constructor;
8use aws_db_esdk::dynamodb::types::ConstructorPart;
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::SignedPart;
13use aws_db_esdk::dynamodb::types::SingleKeyStore;
14use aws_db_esdk::dynamodb::types::StandardBeacon;
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 std::collections::HashMap;
24
25pub async fn setup_beacon_config(
40 ddb_table_name: &str,
41 branch_key_id: &str,
42 branch_key_wrapping_kms_key_arn: &str,
43 branch_key_ddb_table_name: &str,
44) -> Result<aws_sdk_dynamodb::Client, crate::BoxError> {
45 let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
48 let key_store_config = KeyStoreConfig::builder()
49 .kms_client(aws_sdk_kms::Client::new(&sdk_config))
50 .ddb_client(aws_sdk_dynamodb::Client::new(&sdk_config))
51 .ddb_table_name(branch_key_ddb_table_name)
52 .logical_key_store_name(branch_key_ddb_table_name)
53 .kms_configuration(KmsConfiguration::KmsKeyArn(
54 branch_key_wrapping_kms_key_arn.to_string(),
55 ))
56 .build()?;
57
58 let key_store = keystore_client::Client::from_conf(key_store_config)?;
59
60 let standard_beacon_list = vec![
66 StandardBeacon::builder()
67 .name("EmployeeID")
68 .length(4)
69 .build()?,
70 StandardBeacon::builder()
71 .name("TicketNumber")
72 .length(4)
73 .build()?,
74 StandardBeacon::builder()
75 .name("ProjectName")
76 .length(4)
77 .build()?,
78 StandardBeacon::builder()
79 .name("EmployeeEmail")
80 .length(4)
81 .build()?,
82 StandardBeacon::builder()
83 .name("CreatorEmail")
84 .length(4)
85 .build()?,
86 StandardBeacon::builder()
87 .name("ProjectStatus")
88 .length(4)
89 .build()?,
90 StandardBeacon::builder()
91 .name("OrganizerEmail")
92 .length(4)
93 .build()?,
94 StandardBeacon::builder()
95 .name("ManagerEmail")
96 .length(4)
97 .build()?,
98 StandardBeacon::builder()
99 .name("AssigneeEmail")
100 .length(4)
101 .build()?,
102 StandardBeacon::builder()
103 .name("Severity")
104 .length(4)
105 .build()?,
106 StandardBeacon::builder()
107 .name("City")
108 .loc("Location.City")
109 .length(4)
110 .build()?,
111 StandardBeacon::builder()
112 .name("Building")
113 .loc("Location.Building")
114 .length(4)
115 .build()?,
116 StandardBeacon::builder()
117 .name("Floor")
118 .loc("Location.Floor")
119 .length(4)
120 .build()?,
121 StandardBeacon::builder()
122 .name("Room")
123 .loc("Location.Room")
124 .length(4)
125 .build()?,
126 StandardBeacon::builder()
127 .name("Desk")
128 .loc("Location.Desk")
129 .length(4)
130 .build()?,
131 ];
132
133 let encrypted_parts_list = vec![
138 EncryptedPart::builder()
139 .name("EmployeeID")
140 .prefix("E-")
141 .build()?,
142 EncryptedPart::builder()
143 .name("TicketNumber")
144 .prefix("T-")
145 .build()?,
146 EncryptedPart::builder()
147 .name("ProjectName")
148 .prefix("P-")
149 .build()?,
150 EncryptedPart::builder()
151 .name("EmployeeEmail")
152 .prefix("EE-")
153 .build()?,
154 EncryptedPart::builder()
155 .name("CreatorEmail")
156 .prefix("CE-")
157 .build()?,
158 EncryptedPart::builder()
159 .name("OrganizerEmail")
160 .prefix("OE-")
161 .build()?,
162 EncryptedPart::builder()
163 .name("ManagerEmail")
164 .prefix("ME-")
165 .build()?,
166 EncryptedPart::builder()
167 .name("AssigneeEmail")
168 .prefix("AE-")
169 .build()?,
170 EncryptedPart::builder()
171 .name("ProjectStatus")
172 .prefix("PSts-")
173 .build()?,
174 EncryptedPart::builder().name("City").prefix("C-").build()?,
175 EncryptedPart::builder()
176 .name("Severity")
177 .prefix("S-")
178 .build()?,
179 EncryptedPart::builder()
180 .name("Building")
181 .prefix("B-")
182 .build()?,
183 EncryptedPart::builder()
184 .name("Floor")
185 .prefix("F-")
186 .build()?,
187 EncryptedPart::builder().name("Room").prefix("R-").build()?,
188 EncryptedPart::builder().name("Desk").prefix("D-").build()?,
189 ];
190
191 let signed_parts_list = vec![
197 SignedPart::builder()
198 .name("TicketModTime")
199 .prefix("M-")
200 .build()?,
201 SignedPart::builder()
202 .name("MeetingStart")
203 .prefix("MS-")
204 .build()?,
205 SignedPart::builder()
206 .name("TimeCardStart")
207 .prefix("TC-")
208 .build()?,
209 SignedPart::builder()
210 .name("ProjectStart")
211 .prefix("PS-")
212 .build()?,
213 ];
214
215 let employee_id_constructor_part = ConstructorPart::builder()
225 .name("EmployeeID")
226 .required(true)
227 .build()?;
228 let ticket_number_constructor_part = ConstructorPart::builder()
229 .name("TicketNumber")
230 .required(true)
231 .build()?;
232 let project_name_constructor_part = ConstructorPart::builder()
233 .name("ProjectName")
234 .required(true)
235 .build()?;
236 let ticket_mod_time_constructor_part = ConstructorPart::builder()
237 .name("TicketModTime")
238 .required(true)
239 .build()?;
240 let meeting_start_constructor_part = ConstructorPart::builder()
241 .name("MeetingStart")
242 .required(true)
243 .build()?;
244 let timecard_start_constructor_part = ConstructorPart::builder()
245 .name("TimeCardStart")
246 .required(true)
247 .build()?;
248 let employee_email_constructor_part = ConstructorPart::builder()
249 .name("EmployeeEmail")
250 .required(true)
251 .build()?;
252 let creator_email_constructor_part = ConstructorPart::builder()
253 .name("CreatorEmail")
254 .required(true)
255 .build()?;
256 let project_status_constructor_part = ConstructorPart::builder()
257 .name("ProjectStatus")
258 .required(true)
259 .build()?;
260 let organizer_email_constructor_part = ConstructorPart::builder()
261 .name("OrganizerEmail")
262 .required(true)
263 .build()?;
264 let project_start_constructor_part = ConstructorPart::builder()
265 .name("ProjectStart")
266 .required(true)
267 .build()?;
268 let manager_email_constructor_part = ConstructorPart::builder()
269 .name("ManagerEmail")
270 .required(true)
271 .build()?;
272 let assignee_email_constructor_part = ConstructorPart::builder()
273 .name("AssigneeEmail")
274 .required(true)
275 .build()?;
276 let city_constructor_part = ConstructorPart::builder()
277 .name("City")
278 .required(true)
279 .build()?;
280 let severity_constructor_part = ConstructorPart::builder()
281 .name("Severity")
282 .required(true)
283 .build()?;
284 let building_constructor_part = ConstructorPart::builder()
285 .name("Building")
286 .required(true)
287 .build()?;
288 let floor_constructor_part = ConstructorPart::builder()
289 .name("Floor")
290 .required(true)
291 .build()?;
292 let room_constructor_part = ConstructorPart::builder()
293 .name("Room")
294 .required(true)
295 .build()?;
296 let desk_constructor_part = ConstructorPart::builder()
297 .name("Desk")
298 .required(true)
299 .build()?;
300
301 let employee_id_constructor = Constructor::builder()
311 .parts(vec![employee_id_constructor_part])
312 .build()?;
313 let ticket_number_constructor = Constructor::builder()
314 .parts(vec![ticket_number_constructor_part])
315 .build()?;
316 let project_name_constructor = Constructor::builder()
317 .parts(vec![project_name_constructor_part])
318 .build()?;
319 let ticket_mod_time_constructor = Constructor::builder()
320 .parts(vec![ticket_mod_time_constructor_part])
321 .build()?;
322 let building_constructor = Constructor::builder()
323 .parts(vec![building_constructor_part.clone()])
324 .build()?;
325
326 let meeting_start_floor_room_constructor = Constructor::builder()
334 .parts(vec![
335 meeting_start_constructor_part,
336 floor_constructor_part.clone(),
337 room_constructor_part,
338 ])
339 .build()?;
340
341 let timecard_start_constructor = Constructor::builder()
342 .parts(vec![timecard_start_constructor_part.clone()])
343 .build()?;
344 let timecard_start_employee_email_constructor = Constructor::builder()
345 .parts(vec![
346 timecard_start_constructor_part,
347 employee_email_constructor_part.clone(),
348 ])
349 .build()?;
350 let creator_email_constructor = Constructor::builder()
351 .parts(vec![creator_email_constructor_part])
352 .build()?;
353 let project_status_constructor = Constructor::builder()
354 .parts(vec![project_status_constructor_part])
355 .build()?;
356 let employee_email_constructor = Constructor::builder()
357 .parts(vec![employee_email_constructor_part])
358 .build()?;
359 let organizer_email_constructor = Constructor::builder()
360 .parts(vec![organizer_email_constructor_part])
361 .build()?;
362 let project_start_constructor = Constructor::builder()
363 .parts(vec![project_start_constructor_part])
364 .build()?;
365 let manager_email_constructor = Constructor::builder()
366 .parts(vec![manager_email_constructor_part])
367 .build()?;
368 let assignee_email_constructor = Constructor::builder()
369 .parts(vec![assignee_email_constructor_part])
370 .build()?;
371 let city_constructor = Constructor::builder()
372 .parts(vec![city_constructor_part])
373 .build()?;
374 let severity_constructor = Constructor::builder()
375 .parts(vec![severity_constructor_part])
376 .build()?;
377 let building_floor_desk_constructor = Constructor::builder()
378 .parts(vec![
379 building_constructor_part,
380 floor_constructor_part,
381 desk_constructor_part,
382 ])
383 .build()?;
384
385 let pk0_constructor_list = vec![
395 employee_id_constructor.clone(),
396 building_constructor,
397 ticket_number_constructor,
398 project_name_constructor.clone(),
399 ];
400 let sk0_constructor_list = vec![
401 ticket_mod_time_constructor.clone(),
402 meeting_start_floor_room_constructor.clone(),
403 timecard_start_employee_email_constructor,
404 project_name_constructor,
405 employee_id_constructor.clone(),
406 ];
407 let pk1_constructor_list = vec![
408 creator_email_constructor,
409 employee_email_constructor,
410 project_status_constructor,
411 organizer_email_constructor,
412 ];
413 let sk1_constructor_list = vec![
414 meeting_start_floor_room_constructor,
415 timecard_start_constructor,
416 ticket_mod_time_constructor.clone(),
417 project_start_constructor,
418 employee_id_constructor,
419 ];
420 let pk2_constructor_list = vec![manager_email_constructor, assignee_email_constructor];
421 let pk3_constructor_list = vec![city_constructor, severity_constructor];
422 let sk3_constructor_list = vec![building_floor_desk_constructor, ticket_mod_time_constructor];
423
424 let compound_beacon_list = vec![
428 CompoundBeacon::builder()
429 .name("PK")
430 .split("~")
431 .constructors(pk0_constructor_list)
432 .build()?,
433 CompoundBeacon::builder()
434 .name("SK")
435 .split("~")
436 .constructors(sk0_constructor_list)
437 .build()?,
438 CompoundBeacon::builder()
439 .name("PK1")
440 .split("~")
441 .constructors(pk1_constructor_list)
442 .build()?,
443 CompoundBeacon::builder()
444 .name("SK1")
445 .split("~")
446 .constructors(sk1_constructor_list)
447 .build()?,
448 CompoundBeacon::builder()
449 .name("PK2")
450 .split("~")
451 .constructors(pk2_constructor_list)
452 .build()?,
453 CompoundBeacon::builder()
454 .name("PK3")
455 .split("~")
456 .constructors(pk3_constructor_list)
457 .build()?,
458 CompoundBeacon::builder()
459 .name("SK3")
460 .split("~")
461 .constructors(sk3_constructor_list)
462 .build()?,
463 ];
464
465 let beacon_versions = BeaconVersion::builder()
467 .standard_beacons(standard_beacon_list)
468 .compound_beacons(compound_beacon_list)
469 .encrypted_parts(encrypted_parts_list)
470 .signed_parts(signed_parts_list)
471 .version(1)
472 .key_store(key_store.clone())
473 .key_source(BeaconKeySource::Single(
474 SingleKeyStore::builder()
475 .key_id(branch_key_id)
476 .cache_ttl(6000)
477 .build()?,
478 ))
479 .build()?;
480 let beacon_versions = vec![beacon_versions];
481
482 let mpl_config = MaterialProvidersConfig::builder().build()?;
484 let mpl = mpl_client::Client::from_conf(mpl_config)?;
485 let kms_keyring = mpl
486 .create_aws_kms_hierarchical_keyring()
487 .branch_key_id(branch_key_id)
488 .key_store(key_store)
489 .ttl_seconds(600)
490 .send()
491 .await?;
492
493 let attribute_actions_on_encrypt = HashMap::from([
495 ("partition_key".to_string(), CryptoAction::SignOnly),
497 ("EmployeeID".to_string(), CryptoAction::EncryptAndSign),
499 ("TicketNumber".to_string(), CryptoAction::EncryptAndSign),
500 ("ProjectName".to_string(), CryptoAction::EncryptAndSign),
501 ("EmployeeName".to_string(), CryptoAction::EncryptAndSign),
502 ("EmployeeEmail".to_string(), CryptoAction::EncryptAndSign),
503 ("CreatorEmail".to_string(), CryptoAction::EncryptAndSign),
504 ("ProjectStatus".to_string(), CryptoAction::EncryptAndSign),
505 ("OrganizerEmail".to_string(), CryptoAction::EncryptAndSign),
506 ("ManagerEmail".to_string(), CryptoAction::EncryptAndSign),
507 ("AssigneeEmail".to_string(), CryptoAction::EncryptAndSign),
508 ("City".to_string(), CryptoAction::EncryptAndSign),
509 ("Severity".to_string(), CryptoAction::EncryptAndSign),
510 ("Location".to_string(), CryptoAction::EncryptAndSign),
511 ("Attendees".to_string(), CryptoAction::EncryptAndSign),
513 ("Subject".to_string(), CryptoAction::EncryptAndSign),
514 ("TicketModTime".to_string(), CryptoAction::SignOnly),
517 ("MeetingStart".to_string(), CryptoAction::SignOnly),
518 ("TimeCardStart".to_string(), CryptoAction::SignOnly),
519 ("EmployeeTitle".to_string(), CryptoAction::SignOnly),
520 ("Description".to_string(), CryptoAction::SignOnly),
521 ("ProjectTarget".to_string(), CryptoAction::SignOnly),
522 ("Hours".to_string(), CryptoAction::SignOnly),
523 ("Role".to_string(), CryptoAction::SignOnly),
524 ("Message".to_string(), CryptoAction::SignOnly),
525 ("ProjectStart".to_string(), CryptoAction::SignOnly),
526 ("Duration".to_string(), CryptoAction::SignOnly),
527 ]);
528
529 let table_config = DynamoDbTableEncryptionConfig::builder()
531 .logical_table_name(ddb_table_name)
532 .partition_key_name("partition_key")
533 .attribute_actions_on_encrypt(attribute_actions_on_encrypt)
534 .keyring(kms_keyring)
535 .search(
536 SearchConfig::builder()
537 .write_version(1)
538 .versions(beacon_versions)
539 .build()?,
540 )
541 .build()?;
542
543 let table_configs = DynamoDbTablesEncryptionConfig::builder()
544 .table_encryption_configs(HashMap::from([(ddb_table_name.to_string(), table_config)]))
545 .build()?;
546
547 let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
549 let dynamo_config = aws_sdk_dynamodb::config::Builder::from(&sdk_config)
550 .interceptor(DbEsdkInterceptor::new(table_configs)?)
551 .build();
552
553 Ok(aws_sdk_dynamodb::Client::from_conf(dynamo_config))
554}