Struct Shared

Source
#[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§

Source§

impl Shared

Source

pub fn other(&self) -> &Option<String>

Calculate beacon values as for this beacon.

Source§

impl Shared

Source

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§

Source§

impl Clone for Shared

Source§

fn clone(&self) -> Shared

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Shared

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Shared

Source§

fn eq(&self, other: &Shared) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for Shared

Auto Trait Implementations§

§

impl Freeze for Shared

§

impl RefUnwindSafe for Shared

§

impl Send for Shared

§

impl Sync for Shared

§

impl Unpin for Shared

§

impl UnwindSafe for Shared

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AnyRef for T
where T: 'static,

Source§

fn as_any_ref(&self) -> &(dyn Any + 'static)

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

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 more
Source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T
where T: ?Sized,

Source§

fn upcast(&self) -> Ptr<T>

Source§

impl<T> UpcastObject<T> for T
where T: ?Sized,

Source§

fn upcast(&self) -> Object<T>

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,