#[non_exhaustive]pub struct Shared {
pub other: Option<String>,
}
Expand description
This beacon should calculate values like another beacon, so they can be compared.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional
Struct { .. }
syntax; cannot be matched against without a wildcard ..
; and struct update syntax will not work.other: Option<String>
Calculate beacon values as for this beacon.
Implementations§
Sourcepub fn builder() -> SharedBuilder
pub fn builder() -> SharedBuilder
Creates a new builder-style object to manufacture Shared
.
Examples found in repository?
examples/searchableencryption/beacon_styles_searchable_encryption.rs (line 87)
56pub 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 // 1. Create Beacons.
62 let standard_beacon_list = vec![
63 // The fruit beacon allows searching on the encrypted fruit attribute
64 // We have selected 30 as an example beacon length, but you should go to
65 // https://docs.aws.amazon.com/database-encryption-sdk/latest/devguide/choosing-beacon-length.html
66 // when creating your beacons.
67 StandardBeacon::builder().name("fruit").length(30).build()?,
68 // The basket beacon allows searching on the encrypted basket attribute
69 // Basket is used as a Set, and therefore needs a beacon style to reflect that.
70 // Further, we need to be able to compare the items in basket to the fruit attribute
71 // so we `share` this beacon with `fruit`.
72 // Since we need both of these things, we use the SharedSet style.
73 StandardBeacon::builder()
74 .name("basket")
75 .length(30)
76 .style(BeaconStyle::SharedSet(
77 SharedSet::builder().other("fruit").build()?,
78 ))
79 .build()?,
80 // The dessert beacon allows searching on the encrypted dessert attribute
81 // We need to be able to compare the dessert attribute to the fruit attribute
82 // so we `share` this beacon with `fruit`.
83 StandardBeacon::builder()
84 .name("dessert")
85 .length(30)
86 .style(BeaconStyle::Shared(
87 Shared::builder().other("fruit").build()?,
88 ))
89 .build()?,
90 // The veggieBeacon allows searching on the encrypted veggies attribute
91 // veggies is used as a Set, and therefore needs a beacon style to reflect that.
92 StandardBeacon::builder()
93 .name("veggies")
94 .length(30)
95 .style(BeaconStyle::AsSet(AsSet::builder().build()?))
96 .build()?,
97 // The work_typeBeacon allows searching on the encrypted work_type attribute
98 // We only use it as part of the compound work_unit beacon,
99 // so we disable its use as a standalone beacon
100 StandardBeacon::builder()
101 .name("work_type")
102 .length(30)
103 .style(BeaconStyle::PartOnly(PartOnly::builder().build()?))
104 .build()?,
105 ];
106
107 // Here we build a compound beacon from work_id and work_type
108 // If we had tried to make a StandardBeacon from work_type, we would have seen an error
109 // because work_type is "PartOnly"
110 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 // 2. Configure the Keystore
125 // These are the same constructions as in the Basic example, which describes these in more detail.
126 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 // 3. Create BeaconVersion.
140 // This is similar to the Basic example
141 let beacon_version = BeaconVersion::builder()
142 .standard_beacons(standard_beacon_list)
143 .compound_beacons(compound_beacon_list)
144 .version(1) // MUST be 1
145 .key_store(key_store.clone())
146 .key_source(BeaconKeySource::Single(
147 SingleKeyStore::builder()
148 // `keyId` references a beacon key.
149 // For every branch key we create in the keystore,
150 // we also create a beacon key.
151 // This beacon key is not the same as the branch key,
152 // but is created with the same ID as the branch key.
153 .key_id(branch_key_id)
154 .cache_ttl(6000)
155 .build()?,
156 ))
157 .build()?;
158 let beacon_versions = vec![beacon_version];
159
160 // 4. Create a Hierarchical Keyring
161 // This is the same configuration as in the Basic example.
162 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 // 5. Configure which attributes are encrypted and/or signed when writing new items.
173 let attribute_actions_on_encrypt = HashMap::from([
174 ("work_id".to_string(), CryptoAction::SignOnly), // Our partition attribute must be SIGN_ONLY
175 ("inspection_date".to_string(), CryptoAction::SignOnly), // Our sort attribute must be SIGN_ONLY
176 ("dessert".to_string(), CryptoAction::EncryptAndSign), // Beaconized attributes must be encrypted
177 ("fruit".to_string(), CryptoAction::EncryptAndSign), // Beaconized attributes must be encrypted
178 ("basket".to_string(), CryptoAction::EncryptAndSign), // Beaconized attributes must be encrypted
179 ("veggies".to_string(), CryptoAction::EncryptAndSign), // Beaconized attributes must be encrypted
180 ("work_type".to_string(), CryptoAction::EncryptAndSign), // Beaconized attributes must be encrypted
181 ]);
182
183 // 6. Create the DynamoDb Encryption configuration for the table we will be writing to.
184 // The beaconVersions are added to the search configuration.
185 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) // MUST be 1
194 .versions(beacon_versions)
195 .build()?,
196 )
197 .build()?;
198
199 // 7. Create config
200 let encryption_config = DynamoDbTablesEncryptionConfig::builder()
201 .table_encryption_configs(HashMap::from([(ddb_table_name.to_string(), table_config)]))
202 .build()?;
203
204 // 8. Create item one, specifically with "dessert != fruit", and "fruit in basket".
205 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 // 9. Create item two, specifically with "dessert == fruit", and "fruit not in basket".
236 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 // 10. Create a new AWS SDK DynamoDb client using the DynamoDb Config above
270 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 // 11. Add the two items
276 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 // 12. Test the first type of Set operation :
289 // Select records where the basket attribute holds a particular value
290 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 // Validate only 1 item was returned: item1
305 assert_eq!(attribute_values.len(), 1);
306 let returned_item = &attribute_values[0];
307 // Validate the item has the expected attributes
308 assert_eq!(returned_item["work_id"], item1["work_id"]);
309
310 // 13. Test the second type of Set operation :
311 // Select records where the basket attribute holds the fruit attribute
312 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 // Validate only 1 item was returned: item1
321 assert_eq!(attribute_values.len(), 1);
322 let returned_item = &attribute_values[0];
323 // Validate the item has the expected attributes
324 assert_eq!(returned_item["work_id"], item1["work_id"]);
325
326 // 14. Test the third type of Set operation :
327 // Select records where the fruit attribute exists in a particular set
328 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 // Validate only 1 item was returned: item1
346 assert_eq!(attribute_values.len(), 1);
347 let returned_item = &attribute_values[0];
348 // Validate the item has the expected attributes
349 assert_eq!(returned_item["work_id"], item2["work_id"]);
350
351 // 15. Test a Shared search. Select records where the dessert attribute matches the fruit attribute
352 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 // Validate only 1 item was returned: item1
361 assert_eq!(attribute_values.len(), 1);
362 let returned_item = &attribute_values[0];
363 // Validate the item has the expected attributes
364 assert_eq!(returned_item["work_id"], item2["work_id"]);
365
366 // 15. Test the AsSet attribute 'veggies' :
367 // Select records where the veggies attribute holds a particular value
368 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 // Validate only 1 item was returned: item1
381 assert_eq!(attribute_values.len(), 1);
382 let returned_item = &attribute_values[0];
383 // Validate the item has the expected attributes
384 assert_eq!(returned_item["work_id"], item2["work_id"]);
385
386 // 16. Test the compound beacon 'work_unit' :
387 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 // Validate only 1 item was returned: item1
402 assert_eq!(attribute_values.len(), 1);
403 let returned_item = &attribute_values[0];
404 // Validate the item has the expected attributes
405 assert_eq!(returned_item["work_id"], item1["work_id"]);
406
407 println!("beacon_styles_searchable_encryption successful.");
408 Ok(())
409}
Trait Implementations§
Auto Trait Implementations§
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreCreates a shared type from an unshared type.