momento_functions_host/aws/auth.rs
1//! Host interfaces for working with AWS credentials
2
3use momento_functions_wit::host::momento::host::aws_auth;
4use momento_functions_wit::host::momento::host::aws_auth::AuthError;
5
6/// Reads AWS credentials from the environment variables
7/// `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` at build time.
8///
9/// This is not the best way to encode AWS access, but it is included as a simple
10/// way to get started with calling AWS.
11///
12/// The credentials must be set in the environment at build time, something like
13/// ```bash
14/// AWS_ACCESS_KEY_ID=$DEVELOPER_KEY_ID \
15/// AWS_SECRET_ACCESS_KEY=$DEVELOPER_SECRET_KEY \
16/// cargo build --target wasm32-wasip2 --release
17/// ```
18///
19/// If your build environment does not have the variables set, the key and secret
20/// will be `UNSET`. It is highly unlikely that this will work for calling AWS.
21///
22/// **Examples:**
23/// ________
24/// Read from the normal environment variables
25/// ```rust
26/// # use momento_functions_host::build_environment_aws_credentials;
27/// let credentials = build_environment_aws_credentials!();
28/// ```
29/// ________
30/// Read from foo_AWS_ACCESS_KEY_ID and foo_AWS_SECRET_ACCESS_KEY
31/// ```rust
32/// # use momento_functions_host::build_environment_aws_credentials;
33/// let credentials = build_environment_aws_credentials!("foo_");
34/// ```
35#[macro_export]
36macro_rules! build_environment_aws_credentials {
37 ($prefix:literal) => {
38 momento_functions_host::aws::auth::Credentials::Hardcoded {
39 access_key_id: option_env!(concat!($prefix, "AWS_ACCESS_KEY_ID"))
40 .unwrap_or("UNSET")
41 .to_string(),
42 secret_access_key: option_env!(concat!($prefix, "AWS_SECRET_ACCESS_KEY"))
43 .unwrap_or("UNSET")
44 .to_string(),
45 }
46 };
47 () => {
48 build_environment_aws_credentials!("")
49 };
50}
51
52/// The authorization strategy to use when connecting to AWS services.
53pub enum Credentials {
54 /// Credentials that are hardcoded in the application.
55 /// You should use a different strategy if you can.
56 ///
57 /// Compiled wasm archives are irretrievable from Momento. The only way to leak
58 /// hardcoded credentials after uploading to Momento is for you to write code to
59 /// exfiltrate them.
60 Hardcoded {
61 /// The AWS access key ID for the IAM user you wish to use
62 access_key_id: String,
63 /// The AWS secret access key for the IAM user you wish to use
64 secret_access_key: String,
65 },
66}
67
68/// A configured AWS credentials provider. This can be used to connect to AWS services.
69pub struct AwsCredentialsProvider {
70 resource: aws_auth::CredentialsProvider,
71}
72
73impl AwsCredentialsProvider {
74 /// The credentials to use when connecting to AWS services.
75 ///
76 /// **Examples:**
77 /// ```rust,no_run
78 /// # // Not run because docs.rs does not run a Momento WIT host environment, of course!
79 /// # // But it does at least compile, to make sure the example is correct.
80 /// # use momento_functions_host::{build_environment_aws_credentials, aws::auth::{AwsCredentialsProvider}};
81 /// let provider = AwsCredentialsProvider::new("us-east-1", build_environment_aws_credentials!());
82 /// ```
83 pub fn new(
84 region: impl AsRef<str>,
85 credentials: Credentials,
86 ) -> Result<AwsCredentialsProvider, AuthError> {
87 let wit_authorization = match credentials {
88 Credentials::Hardcoded {
89 access_key_id,
90 secret_access_key,
91 } => aws_auth::Authorization::Hardcoded(aws_auth::Credentials {
92 access_key_id,
93 secret_access_key,
94 }),
95 };
96
97 let resource = aws_auth::provider(&wit_authorization, region.as_ref())?;
98
99 momento_functions_wit::host::momento::host::aws_ddb::Client::new(&resource);
100
101 Ok(AwsCredentialsProvider { resource })
102 }
103
104 /// Returns the underlying WIT resource.
105 pub(crate) fn resource(&self) -> &aws_auth::CredentialsProvider {
106 &self.resource
107 }
108}