Skip to content

Commit 95d9d7c

Browse files
committed
backup
1 parent bf43328 commit 95d9d7c

File tree

79 files changed

+12759
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+12759
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target
2+
*.pem
3+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
[package]
3+
name = "aws-esdk"
4+
version = "0.1.0"
5+
edition = "2024"
6+
autoexamples = false
7+
8+
[dependencies]
9+
aws-mpl-rs = { path = "/Users/ajewell/h2/aws-cryptographic-material-providers-library/AwsCryptographicMaterialProviders/runtimes/rust" }
10+
aws-smithy-types = "1.3.3"
11+
tokio = "1.48.0"
12+
aws-mpl-primitives = { path = "/Users/ajewell/esdk_rust/prim" }
13+
derivative = "2.2.0"
14+
derive_builder = "0.20.2"
15+
16+
clap = { version = "4.5.49", features = ["derive"], optional = true }
17+
serde_json = { version = "1.0.145", optional = true }
18+
anyhow = { version = "1.0.100", optional = true }
19+
base64 = { version = "0.22.1", optional = true }
20+
aws-sdk-kms = { version = "1.90.0", optional = true }
21+
aws-config = { version = "1.8.8", optional = true }
22+
23+
# Necessary for examples
24+
[dev-dependencies]
25+
pem = "3.0.6"
26+
aws-config = "1.8.8"
27+
aws-sdk-kms = "1.90.0"
28+
aws-sdk-dynamodb = "1.95.0"
29+
aws-lc-rs = {version = "1.14.1"}
30+
rand = "0.9.2"
31+
32+
[[example]]
33+
name = "main"
34+
35+
[[bin]]
36+
name = "test_vector"
37+
path = "src/bin/test_vector/main.rs"
38+
required-features = ["test_vectors"] # Only build binary when cli feature is enabled
39+
40+
[features]
41+
default = []
42+
test_vectors = ["clap", "serde_json", "anyhow", "base64", "aws-sdk-kms", "aws-config"] # Users can enable with --features test_vectors
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# AWS Encryption SDK for Rust Examples
2+
3+
This section features examples that show you
4+
how to use the AWS Encryption SDK.
5+
We demonstrate how to use the encryption and decryption APIs
6+
and how to set up some common configuration patterns.
7+
8+
## APIs
9+
10+
The AWS Encryption SDK provides a high-level,
11+
one-step API that processes encryption
12+
and decryption operations entirely in memory.
13+
14+
You can find examples that demonstrate these APIs
15+
in the [`examples/`](./) directory.
16+
17+
- [How to encrypt and decrypt](./keyring/aws_kms_keyring_example.rs)
18+
- [How to change the algorithm suite](./set_encryption_algorithm_suite_example.rs)
19+
- [How to set the commitment policy](./set_commitment_policy_example.rs)
20+
- [How to limit the number of encrypted data keys (EDKs)](./limit_encrypted_data_keys_example.rs)
21+
22+
## Configuration
23+
24+
To use the encryption and decryption APIs,
25+
you need to describe how you want the library to protect your data keys.
26+
You can do this by configuring
27+
[keyrings](#keyrings) or [cryptographic materials managers](#cryptographic-materials-managers).
28+
These examples will show you how to use the configuration tools that we include for you
29+
and how to create some of your own.
30+
We start with AWS KMS examples, then show how to use other wrapping keys.
31+
32+
- Using AWS Key Management Service (AWS KMS)
33+
- [How to use one AWS KMS key](./keyring/aws_kms_keyring_example.rs)
34+
- [How to use multiple AWS KMS keys in different regions](./keyring/aws_kms_mrk_discovery_multi_keyring_example.rs)
35+
- [How to decrypt when you don't know the AWS KMS key](./keyring/aws_kms_discovery_keyring_example.rs)
36+
- [How to limit decryption to a single region](./keyring/aws_kms_mrk_discovery_keyring_example.rs)
37+
- [How to decrypt with a preferred region but failover to others](./keyring/aws_kms_mrk_discovery_multi_keyring_example.rs)
38+
- [How to reproduce the behavior of an AWS KMS master key provider](./keyring/aws_kms_multi_keyring_example.rs)
39+
- Using raw wrapping keys
40+
- [How to use a raw AES wrapping key](./keyring/raw_aes_keyring_example.rs)
41+
- [How to use a raw RSA wrapping key](./keyring/raw_rsa_keyring_example.rs)
42+
- Combining wrapping keys
43+
- [How to combine AWS KMS with an offline escrow key](./keyring/multi_keyring_example.rs)
44+
- How to restrict algorithm suites
45+
- [with a custom cryptographic materials manager](./cryptographic_materials_manager/restrict_algorithm_suite/signing_suite_only_cmm.rs)
46+
47+
### Keyrings
48+
49+
Keyrings are the most common way for you to configure the AWS Encryption SDK.
50+
They determine how the AWS Encryption SDK protects your data.
51+
For more information about keyrings, see the [AWS Developer Guide on using Keyrings](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html).
52+
You can find these examples in [`examples/keyring`](./keyring).
53+
54+
### Cryptographic Materials Managers
55+
56+
Keyrings define how your data keys are protected,
57+
but there is more going on here than just protecting data keys.
58+
59+
Cryptographic materials managers give you higher-level controls
60+
over how the AWS Encryption SDK protects your data.
61+
This can include things like
62+
enforcing the use of certain algorithm suites or encryption context settings,
63+
reusing data keys across messages,
64+
or changing how you interact with keyrings.
65+
For more information about cryptographic materials managers, see the [AWS Developer Guide on cryptographic materials managers](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#crypt-materials-manager).
66+
You can find these examples in
67+
[`examples/cryptographic_materials_manager`](./cryptographic_materials_manager).
68+
69+
### Client Supplier
70+
71+
The AWS Encryption SDK creates AWS KMS clients when interacting with AWS KMS.
72+
In case the default AWS KMS client configuration doesn't suit your needs,
73+
you can configure clients by defining a custom Client Supplier.
74+
For example, your Client Supplier could tune
75+
the retry and timeout settings on the client, or use different credentials
76+
based on which region is being called. In our
77+
[regional_role_client_supplier](./client_supplier/regional_role_client_supplier.rs)
78+
example, we show how you can build a custom Client Supplier which
79+
creates clients by assuming different IAM roles for different regions.
80+
81+
# Writing Examples
82+
83+
If you want to contribute a new example, that's awesome!
84+
To make sure that your example is tested in our CI,
85+
please make sure that it meets the following requirements:
86+
87+
1. The example MUST be a distinct subdirectory or file in the [`examples/`](./) directory.
88+
1. The example MAY be nested arbitrarily deeply. However, each example file MUST be added to the `mod.rs` files appropriately according to the directory structure. If the example is in the root directory [`examples/`](./), you MUST also add the module to the [`main.rs`](./main.rs) file. For instance, `pub mod set_commitment_policy_example;`.
89+
1. Each example file MUST contain exactly one example.
90+
1. Each example filename MUST be descriptive.
91+
1. Each example file MUST contain a testing function with the attribute `#[tokio::test(flavor = "multi_thread")]` just like the one at the end of the [KMS Keyring](./keyring/aws_kms_keyring_example.rs).
92+
1. Each example MUST also be called inside the `main` function of [main.rs](./main.rs).
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
/*
5+
This example sets up an MRK multi-keyring and an MRK discovery
6+
multi-keyring using a custom client supplier.
7+
A custom client supplier grants users access to more granular
8+
configuration aspects of their authentication details and KMS
9+
client. In this example, we create a simple custom client supplier
10+
that authenticates with a different IAM role based on the
11+
region of the KMS key.
12+
13+
This example creates a MRK multi-keyring configured with a custom
14+
client supplier using a single MRK and encrypts the example_data with it.
15+
Then, it creates a MRK discovery multi-keyring to decrypt the ciphertext.
16+
*/
17+
18+
use super::regional_role_client_supplier::RegionalRoleClientSupplier;
19+
use aws_esdk::client as esdk_client;
20+
use aws_esdk::material_providers::client as mpl_client;
21+
use aws_esdk::material_providers::types::DiscoveryFilter;
22+
use aws_esdk::material_providers::types::error::Error::AwsCryptographicMaterialProvidersException;
23+
use aws_esdk::material_providers::types::material_providers_config::MaterialProvidersConfig;
24+
use aws_esdk::types::*;
25+
26+
pub async fn encrypt_and_decrypt_with_keyring(
27+
example_data: &str,
28+
mrk_key_id_encrypt: &str,
29+
aws_account_id: &str,
30+
aws_regions: Vec<String>,
31+
) -> Result<(), crate::BoxError> {
32+
// 1. Instantiate the encryption SDK client.
33+
// This builds the default client with the RequireEncryptRequireDecrypt commitment policy,
34+
// which enforces that this client only encrypts using committing algorithm suites and enforces
35+
// that this client will only decrypt encrypted messages that were created with a committing
36+
// algorithm suite.
37+
let esdk_config = AwsEncryptionSdkConfig::default();
38+
let esdk_client = esdk_client::Client::from_conf(esdk_config)?;
39+
40+
// 2. Create encryption context.
41+
// Remember that your encryption context is NOT SECRET.
42+
// For more information, see
43+
// https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
44+
let encryption_context = EncryptionContext::from([
45+
("encryption".to_string(), "context".to_string()),
46+
("is not".to_string(), "secret".to_string()),
47+
("but adds".to_string(), "useful metadata".to_string()),
48+
(
49+
"that can help you".to_string(),
50+
"be confident that".to_string(),
51+
),
52+
(
53+
"the data you are handling".to_string(),
54+
"is what you think it is".to_string(),
55+
),
56+
]);
57+
58+
// 3. Create a single MRK multi-keyring.
59+
// This can be either a single-region KMS key or an MRK.
60+
// For this example to succeed, the key's region must either
61+
// 1) be in the regions list, or
62+
// 2) the key must be an MRK with a replica defined
63+
// in a region in the regions list, and the client
64+
// must have the correct permissions to access the replica.
65+
let mpl_config = MaterialProvidersConfig::builder().build()?;
66+
let mpl = mpl_client::Client::from_conf(mpl_config)?;
67+
68+
// Create the multi-keyring using our custom client supplier
69+
// defined in the RegionalRoleClientSupplier class in this directory.
70+
// Note: RegionalRoleClientSupplier will internally use the key_arn's region
71+
// to retrieve the correct IAM role.
72+
let mrk_keyring_with_client_supplier = mpl
73+
.create_aws_kms_mrk_multi_keyring()
74+
.client_supplier(RegionalRoleClientSupplier {})
75+
.generator(mrk_key_id_encrypt)
76+
.send()
77+
.await?;
78+
79+
// 4. Encrypt the data with the encryption_context using the encrypt_keyring.
80+
let plaintext = example_data.as_bytes();
81+
82+
let encrypt_input = EncryptInputBuilder::default()
83+
.plaintext(plaintext)
84+
.keyring(mrk_keyring_with_client_supplier)
85+
.encryption_context(&encryption_context)
86+
.build()?;
87+
let encryption_response = esdk_client.encrypt(&encrypt_input).await?;
88+
89+
let ciphertext = encryption_response.ciphertext;
90+
91+
// 5. Demonstrate that the ciphertext and plaintext are different.
92+
// (This is an example for demonstration; you do not need to do this in your own code.)
93+
assert_ne!(
94+
ciphertext, plaintext,
95+
"Ciphertext and plaintext data are the same. Invalid encryption"
96+
);
97+
98+
// 6. Create a MRK discovery multi-keyring with a custom client supplier.
99+
// A discovery MRK multi-keyring will be composed of
100+
// multiple discovery MRK keyrings, one for each region.
101+
// Each component keyring has its own KMS client in a particular region.
102+
// When we provide a client supplier to the multi-keyring, all component
103+
// keyrings will use that client supplier configuration.
104+
// In our tests, we make `mrk_key_id_encrypt` an MRK with a replica, and
105+
// provide only the replica region in our discovery filter.
106+
let discovery_filter = DiscoveryFilter::builder()
107+
.account_ids(vec![aws_account_id.to_string()])
108+
.partition("aws".to_string())
109+
.build()?;
110+
111+
let mrk_discovery_client_supplier_keyring = mpl
112+
.create_aws_kms_mrk_discovery_multi_keyring()
113+
.client_supplier(RegionalRoleClientSupplier {})
114+
.discovery_filter(discovery_filter.clone())
115+
.regions(aws_regions)
116+
.send()
117+
.await?;
118+
119+
// 7. Decrypt your encrypted data using the discovery multi keyring.
120+
// On Decrypt, the header of the encrypted message (ciphertext) will be parsed.
121+
// The header contains the Encrypted Data Keys (EDKs), which, if the EDK
122+
// was encrypted by a KMS Keyring, includes the KMS Key ARN.
123+
// For each member of the Multi Keyring, every EDK will try to be decrypted until a decryption
124+
// is successful.
125+
// Since every member of the Multi Keyring is a Discovery Keyring:
126+
// Each Keyring will filter the EDKs by the Discovery Filter and the Keyring's region.
127+
// For each filtered EDK, the keyring will attempt decryption with the keyring's client.
128+
// All of this is done serially, until a success occurs or all keyrings have failed
129+
// all (filtered) EDKs. KMS MRK Discovery Keyrings will attempt to decrypt
130+
// Multi Region Keys (MRKs) and regular KMS Keys.
131+
let decrypt_input = DecryptInputBuilder::default()
132+
.ciphertext(&ciphertext)
133+
.keyring(mrk_discovery_client_supplier_keyring)
134+
// Provide the encryption context that was supplied to the encrypt method
135+
.encryption_context(&encryption_context)
136+
.build()?;
137+
let decryption_response = esdk_client.decrypt(&decrypt_input).await?;
138+
139+
let decrypted_plaintext = decryption_response.plaintext;
140+
141+
// 8. Demonstrate that the decrypted plaintext is identical to the original plaintext.
142+
// (This is an example for demonstration; you do not need to do this in your own code.)
143+
assert_eq!(
144+
decrypted_plaintext, plaintext,
145+
"Decrypted plaintext should be identical to the original plaintext. Invalid decryption"
146+
);
147+
148+
// 9. Test the Missing Region Exception
149+
// (This is an example for demonstration; you do not need to do this in your own code.)
150+
let mrk_discovery_client_supplier_keyring_missing_region = mpl
151+
.create_aws_kms_mrk_discovery_multi_keyring()
152+
.client_supplier(RegionalRoleClientSupplier {})
153+
.discovery_filter(discovery_filter)
154+
.regions(vec!["fake-region".to_string()])
155+
.send()
156+
.await;
157+
158+
// Swallow the exception
159+
// (This is an example for demonstration; you do not need to do this in your own code.)
160+
match mrk_discovery_client_supplier_keyring_missing_region {
161+
Ok(_) => panic!(
162+
"Decryption using discovery keyring with missing region MUST \
163+
raise AwsCryptographicMaterialProvidersException"
164+
),
165+
Err(AwsCryptographicMaterialProvidersException { message: _e }) => (),
166+
_ => panic!("Unexpected error type"),
167+
}
168+
169+
println!("Client Supplier Example Completed Successfully");
170+
171+
Ok(())
172+
}
173+
174+
#[tokio::test(flavor = "multi_thread")]
175+
pub async fn test_encrypt_and_decrypt_with_keyring() -> Result<(), crate::BoxError2> {
176+
// Test function for encrypt and decrypt using the Client Supplier example
177+
use crate::example_utils::utils;
178+
179+
// Note that we pass in an MRK in us-east-1. The RegionalRoleClientSupplier
180+
// will internally use the key_arn's region (us-east-1)
181+
// to retrieve the correct IAM role.
182+
// and access its replica in eu-west-1
183+
let aws_regions: Vec<String> = vec!["eu-west-1".to_string()];
184+
185+
encrypt_and_decrypt_with_keyring(
186+
utils::TEST_EXAMPLE_DATA,
187+
utils::TEST_MRK_KEY_ID_US_EAST_1,
188+
utils::TEST_DEFAULT_KMS_KEY_ACCOUNT_ID,
189+
aws_regions,
190+
)
191+
.await?;
192+
193+
Ok(())
194+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
pub mod client_supplier_example;
5+
pub mod regional_role_client_supplier;
6+
pub mod regional_role_client_supplier_config;

0 commit comments

Comments
 (0)