main/migration/plaintext_to_awsdbe/awsdbe/common.rs
1// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use aws_db_esdk::dynamodb::types::DynamoDbTableEncryptionConfig;
5use aws_db_esdk::dynamodb::types::PlaintextOverride;
6use aws_db_esdk::material_providers::client;
7use aws_db_esdk::material_providers::types::material_providers_config::MaterialProvidersConfig;
8use aws_db_esdk::types::dynamo_db_tables_encryption_config::DynamoDbTablesEncryptionConfig;
9use aws_db_esdk::CryptoAction;
10use std::collections::HashMap;
11
12pub async fn create_table_configs(
13 kms_key_id: &str,
14 ddb_table_name: &str,
15 plaintext_override: PlaintextOverride,
16) -> Result<DynamoDbTablesEncryptionConfig, Box<dyn std::error::Error>> {
17 // Create a Keyring. This Keyring will be responsible for protecting the data keys that protect your data.
18 // For this example, we will create a AWS KMS Keyring with the AWS KMS Key we want to use.
19 // We will use the `CreateMrkMultiKeyring` method to create this keyring,
20 // as it will correctly handle both single region and Multi-Region KMS Keys.
21 let provider_config = MaterialProvidersConfig::builder().build()?;
22 let mat_prov = client::Client::from_conf(provider_config)?;
23 let kms_keyring = mat_prov
24 .create_aws_kms_mrk_multi_keyring()
25 .generator(kms_key_id)
26 .send()
27 .await?;
28
29 // Configure which attributes are encrypted and/or signed when writing new items.
30 // For each attribute that may exist on the items we plan to write to our DynamoDbTable,
31 // we must explicitly configure how they should be treated during item encryption:
32 // - ENCRYPT_AND_SIGN: The attribute is encrypted and included in the signature
33 // - SIGN_ONLY: The attribute not encrypted, but is still included in the signature
34 // - DO_NOTHING: The attribute is not encrypted and not included in the signature
35 let partition_key_name = "partition_key";
36 let sort_key_name = "sort_key";
37 let attribute_actions_on_encrypt = HashMap::from([
38 (partition_key_name.to_string(), CryptoAction::SignOnly),
39 (sort_key_name.to_string(), CryptoAction::SignOnly),
40 ("attribute1".to_string(), CryptoAction::EncryptAndSign),
41 ("attribute2".to_string(), CryptoAction::SignOnly),
42 ("attribute3".to_string(), CryptoAction::DoNothing),
43 ]);
44
45 // Configure which attributes we expect to be excluded in the signature
46 // when reading items. There are two options for configuring this:
47 //
48 // - (Recommended) Configure `allowedUnsignedAttributesPrefix`:
49 // When defining your DynamoDb schema and deciding on attribute names,
50 // choose a distinguishing prefix (such as ":") for all attributes that
51 // you do not want to include in the signature.
52 // This has two main benefits:
53 // - It is easier to reason about the security and authenticity of data within your item
54 // when all unauthenticated data is easily distinguishable by their attribute name.
55 // - If you need to add new unauthenticated attributes in the future,
56 // you can easily make the corresponding update to your `attributeActionsOnEncrypt`
57 // and immediately start writing to that new attribute, without
58 // any other configuration update needed.
59 // Once you configure this field, it is not safe to update it.
60 //
61 // - Configure `allowedUnsignedAttributes`: You may also explicitly list
62 // a set of attributes that should be considered unauthenticated when encountered
63 // on read. Be careful if you use this configuration. Do not remove an attribute
64 // name from this configuration, even if you are no longer writing with that attribute,
65 // as old items may still include this attribute, and our configuration needs to know
66 // to continue to exclude this attribute from the signature scope.
67 // If you add new attribute names to this field, you must first deploy the update to this
68 // field to all readers in your host fleet before deploying the update to start writing
69 // with that new attribute.
70 //
71 // For this example, we will explicitly list the attributes that are not signed.
72 let unsigned_attributes = vec!["attribute3".to_string()];
73
74 // Create the DynamoDb Encryption configuration for the table we will be writing to.
75 let table_config = DynamoDbTableEncryptionConfig::builder()
76 .logical_table_name(ddb_table_name)
77 .partition_key_name(partition_key_name)
78 .sort_key_name(sort_key_name)
79 .attribute_actions_on_encrypt(attribute_actions_on_encrypt)
80 .keyring(kms_keyring)
81 .allowed_unsigned_attributes(unsigned_attributes)
82 .plaintext_override(plaintext_override)
83 .build()?;
84
85 let table_configs = DynamoDbTablesEncryptionConfig::builder()
86 .table_encryption_configs(HashMap::from([(ddb_table_name.to_string(), table_config)]))
87 .build()?;
88
89 Ok(table_configs)
90}