1use crate::config::AwsConfig;
4use aws_config::BehaviorVersion;
5use aws_config::meta::region::RegionProviderChain;
6use aws_config::sts::AssumeRoleProvider;
7use aws_credential_types::Credentials;
8use aws_sdk_kinesis::Client as KinesisClient;
9use aws_sdk_s3::Client as S3Client;
10use aws_sdk_sqs::Client as SqsClient;
11use snafu::Snafu;
12use std::time::Duration;
13
14#[derive(Debug, Snafu)]
15pub enum Error {
16 #[snafu(display("Failed to load AWS configuration: {}", source))]
17 ConfigLoad { source: std::io::Error }, }
19
20pub type Result<T, E = Error> = std::result::Result<T, E>;
21
22pub async fn load_config(config: &AwsConfig) -> aws_config::SdkConfig {
24 let region_provider =
25 RegionProviderChain::first_try(config.region.clone().map(aws_config::Region::new))
26 .or_default_provider()
27 .or_else(aws_config::Region::new("us-east-1"));
28
29 let mut loader = aws_config::defaults(BehaviorVersion::latest()).region(region_provider);
30
31 if let Some(endpoint) = &config.endpoint {
32 loader = loader.endpoint_url(endpoint);
33 }
34
35 if let Some(access_key) = &config.access_key_id {
37 tracing::warn!(
38 "AWS credentials (access_key_id/secret_access_key) are explicitly set. For better security, consider using IAM roles, instance profiles, or injected environment variables."
39 );
40 if let Some(secret_key) = &config.secret_access_key {
41 let creds = Credentials::new(
42 access_key.clone(),
43 secret_key.clone(),
44 config.session_token.clone(),
45 None,
46 "manual",
47 );
48 loader = loader.credentials_provider(creds);
49 }
50 } else if let Some(profile) = &config.profile {
51 let profile_builder =
52 aws_config::profile::ProfileFileCredentialsProvider::builder().profile_name(profile);
53 loader = loader.credentials_provider(profile_builder.build());
54 } else if let Some(imds_config) = &config.imds {
55 let mut imds_client_builder = aws_config::imds::client::Client::builder();
56 if let Some(timeout) = imds_config.connect_timeout_seconds {
57 imds_client_builder = imds_client_builder.connect_timeout(Duration::from_secs(timeout));
58 }
59 if let Some(timeout) = imds_config.read_timeout_seconds {
60 imds_client_builder = imds_client_builder.read_timeout(Duration::from_secs(timeout));
61 }
62
63 let imds_provider = aws_config::imds::credentials::ImdsCredentialsProvider::builder()
64 .imds_client(imds_client_builder.build())
65 .build();
66
67 loader = loader.credentials_provider(imds_provider);
68 }
69
70 let mut sdk_config = loader.load().await;
71
72 if let Some(role_arn) = &config.assume_role {
74 let mut role_builder = AssumeRoleProvider::builder(role_arn).configure(&sdk_config);
75
76 if let Some(session_name) = &config.session_name {
77 role_builder = role_builder.session_name(session_name);
78 }
79 if let Some(external_id) = &config.external_id {
80 role_builder = role_builder.external_id(external_id);
81 }
82
83 let role_provider = role_builder.build().await;
84
85 sdk_config = aws_config::defaults(BehaviorVersion::latest())
87 .region(sdk_config.region().cloned())
88 .credentials_provider(role_provider)
89 .load()
90 .await;
91 }
92
93 sdk_config
94}
95
96pub async fn create_s3_client(config: &AwsConfig) -> S3Client {
98 let sdk_config = load_config(config).await;
99 S3Client::new(&sdk_config)
100}
101
102pub async fn create_sqs_client(config: &AwsConfig) -> SqsClient {
104 let sdk_config = load_config(config).await;
105 SqsClient::new(&sdk_config)
106}
107
108pub async fn create_kinesis_client(config: &AwsConfig) -> KinesisClient {
110 let sdk_config = load_config(config).await;
111 KinesisClient::new(&sdk_config)
112}