#[non_exhaustive]pub struct AsSet {}
Expand description
Attribute must be a Set. Beacon value will also be a Set.
Implementations§
Source§impl AsSet
impl AsSet
Sourcepub fn builder() -> AsSetBuilder
pub fn builder() -> AsSetBuilder
Creates a new builder-style object to manufacture AsSet
.
Examples found in repository?
examples/searchableencryption/beacon_styles_searchable_encryption.rs (line 95)
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§
impl StructuralPartialEq for AsSet
Auto Trait Implementations§
impl Freeze for AsSet
impl RefUnwindSafe for AsSet
impl Send for AsSet
impl Sync for AsSet
impl Unpin for AsSet
impl UnwindSafe for AsSet
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.