use crate::test_utils;
use aws_sdk_dynamodb::types::AttributeValue;
use std::collections::HashMap;
use aws_db_esdk::material_providers::client;
use aws_db_esdk::material_providers::types::material_providers_config::MaterialProvidersConfig;
use aws_db_esdk::CryptoAction;
use aws_db_esdk::dynamodb::types::BeaconKeySource;
use aws_db_esdk::dynamodb::types::BeaconVersion;
use aws_db_esdk::dynamodb::types::DynamoDbTableEncryptionConfig;
use aws_db_esdk::dynamodb::types::SearchConfig;
use aws_db_esdk::dynamodb::types::SingleKeyStore;
use aws_db_esdk::dynamodb::types::StandardBeacon;
use aws_db_esdk::intercept::DbEsdkInterceptor;
use aws_db_esdk::key_store::client as keystore_client;
use aws_db_esdk::key_store::types::key_store_config::KeyStoreConfig;
use aws_db_esdk::key_store::types::KmsConfiguration;
use aws_db_esdk::types::dynamo_db_tables_encryption_config::DynamoDbTablesEncryptionConfig;
const GSI_NAME: &str = "last4-unit-index";
pub async fn put_and_query_with_beacon(branch_key_id: &str) -> Result<(), crate::BoxError> {
let future = async move {
let ddb_table_name = test_utils::UNIT_INSPECTION_TEST_DDB_TABLE_NAME;
let branch_key_wrapping_kms_key_arn = test_utils::TEST_BRANCH_KEY_WRAPPING_KMS_KEY_ARN;
let branch_key_ddb_table_name = test_utils::TEST_BRANCH_KEYSTORE_DDB_TABLE_NAME;
let last4_beacon = StandardBeacon::builder()
.name("inspector_id_last4")
.length(10)
.build()?;
let unit_beacon = StandardBeacon::builder().name("unit").length(30).build()?;
let standard_beacon_list = vec![last4_beacon, unit_beacon];
let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
let key_store_config = KeyStoreConfig::builder()
.kms_client(aws_sdk_kms::Client::new(&sdk_config))
.ddb_client(aws_sdk_dynamodb::Client::new(&sdk_config))
.ddb_table_name(branch_key_ddb_table_name)
.logical_key_store_name(branch_key_ddb_table_name)
.kms_configuration(KmsConfiguration::KmsKeyArn(
branch_key_wrapping_kms_key_arn.to_string(),
))
.build()?;
let key_store = keystore_client::Client::from_conf(key_store_config)?;
let beacon_version = BeaconVersion::builder()
.standard_beacons(standard_beacon_list)
.version(1) .key_store(key_store.clone())
.key_source(BeaconKeySource::Single(
SingleKeyStore::builder()
.key_id(branch_key_id)
.cache_ttl(6000)
.build()?,
))
.build()?;
let beacon_versions = vec![beacon_version];
let provider_config = MaterialProvidersConfig::builder().build()?;
let mat_prov = client::Client::from_conf(provider_config)?;
let kms_keyring = mat_prov
.create_aws_kms_hierarchical_keyring()
.branch_key_id(branch_key_id)
.key_store(key_store)
.ttl_seconds(6000)
.send()
.await?;
let attribute_actions_on_encrypt = HashMap::from([
("work_id".to_string(), CryptoAction::SignOnly), ("inspection_date".to_string(), CryptoAction::SignOnly), (
"inspector_id_last4".to_string(),
CryptoAction::EncryptAndSign,
), ("unit".to_string(), CryptoAction::EncryptAndSign), ]);
let table_config = DynamoDbTableEncryptionConfig::builder()
.logical_table_name(ddb_table_name)
.partition_key_name("work_id")
.sort_key_name("inspection_date")
.attribute_actions_on_encrypt(attribute_actions_on_encrypt)
.keyring(kms_keyring)
.search(
SearchConfig::builder()
.write_version(1) .versions(beacon_versions)
.build()?,
)
.build()?;
let table_configs = DynamoDbTablesEncryptionConfig::builder()
.table_encryption_configs(HashMap::from([(ddb_table_name.to_string(), table_config)]))
.build()?;
let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
let dynamo_config = aws_sdk_dynamodb::config::Builder::from(&sdk_config)
.interceptor(DbEsdkInterceptor::new(table_configs)?)
.build();
let ddb = aws_sdk_dynamodb::Client::from_conf(dynamo_config);
let item = HashMap::from([
(
"work_id".to_string(),
AttributeValue::S("1313ba89-5661-41eb-ba6c-cb1b4cb67b2d".to_string()),
),
(
"inspection_date".to_string(),
AttributeValue::S("2023-06-13".to_string()),
),
(
"inspector_id_last4".to_string(),
AttributeValue::S("4321".to_string()),
),
(
"unit".to_string(),
AttributeValue::S("123456789012".to_string()),
),
]);
ddb.put_item()
.table_name(ddb_table_name)
.set_item(Some(item.clone()))
.send()
.await?;
let expression_attributes_names = HashMap::from([
("#last4".to_string(), "inspector_id_last4".to_string()),
("#unit".to_string(), "unit".to_string()),
]);
let expression_attribute_values = HashMap::from([
(":last4".to_string(), AttributeValue::S("4321".to_string())),
(
":unit".to_string(),
AttributeValue::S("123456789012".to_string()),
),
]);
for _i in 0..10 {
let query_response = ddb
.query()
.table_name(ddb_table_name)
.index_name(GSI_NAME)
.key_condition_expression("#last4 = :last4 and #unit = :unit")
.set_expression_attribute_names(Some(expression_attributes_names.clone()))
.set_expression_attribute_values(Some(expression_attribute_values.clone()))
.send()
.await?;
if query_response.items.is_none() || query_response.items.as_ref().unwrap().is_empty() {
std::thread::sleep(std::time::Duration::from_millis(20));
continue;
}
let attribute_values = query_response.items.unwrap();
assert_eq!(attribute_values.len(), 1);
let returned_item = &attribute_values[0];
assert_eq!(
returned_item["inspector_id_last4"],
AttributeValue::S("4321".to_string())
);
assert_eq!(
returned_item["unit"],
AttributeValue::S("123456789012".to_string())
);
break;
}
println!("basic_searchable_encryption successful.");
Ok(())
};
future.await
}