cloud_file_signer/aws/
mod.rs1use std::time::Duration;
4use std::time::SystemTime;
5
6use aws_config::SdkConfig;
7use aws_sdk_s3::error::SdkError;
8use aws_sdk_s3::operation::get_object::GetObjectError;
9use aws_sdk_s3::presigning::PresigningConfig;
10use aws_sdk_s3::presigning::PresigningConfigError;
11use aws_sdk_s3::Client;
12
13use crate::error::SignerError;
14use crate::permissions::Permission;
15use crate::presigned_url::PresignedUrl;
16use crate::CloudFileSigner;
17
18mod uri;
19
20#[derive(Debug, Clone)]
22pub struct S3FileSigner {
23 client: Client,
24}
25
26impl S3FileSigner {
27 #[must_use]
29 pub fn new(client: Client) -> Self {
30 Self { client }
31 }
32
33 pub async fn from_config(config: &SdkConfig) -> Self {
35 let client = Client::new(config);
36 Self { client }
37 }
38
39 pub async fn from_env() -> Self {
41 let config = aws_config::load_from_env().await;
42 let client = Client::new(&config);
43 Self { client }
44 }
45}
46
47impl S3FileSigner {
48 async fn sign_get_request(
49 &self,
50 uri: &uri::S3Uri,
51 expiration: Duration,
52 ) -> Result<PresignedUrl, SignerError> {
53 let valid_from = SystemTime::now();
54
55 let cfg = PresigningConfig::builder().expires_in(expiration).build()?;
56 let presigned_request = self
57 .client
58 .get_object()
59 .bucket(uri.bucket())
60 .key(uri.key())
61 .presigned(cfg)
62 .await?;
63
64 Ok(PresignedUrl::new(
65 presigned_request.uri().to_string(),
66 valid_from,
67 expiration,
68 ))
69 }
70}
71
72#[async_trait::async_trait]
73impl CloudFileSigner for S3FileSigner {
74 async fn sign(
75 &self,
76 path: &str,
77 _valid_from: SystemTime,
78 expiration: Duration,
79 permission: Permission,
80 ) -> Result<PresignedUrl, SignerError> {
81 let s3_uri = path.parse::<uri::S3Uri>()?;
82 match permission {
83 Permission::Read => Ok(self.sign_get_request(&s3_uri, expiration).await?),
84 _ => Err(SignerError::permission_not_supported(format!(
85 "permission {permission:?} not supported"
86 ))),
87 }
88 }
89}
90
91impl From<PresigningConfigError> for SignerError {
92 fn from(e: PresigningConfigError) -> Self {
93 SignerError::other_error(format!("Other error: {e}"))
94 }
95}
96
97impl From<GetObjectError> for SignerError {
98 fn from(e: GetObjectError) -> Self {
99 SignerError::other_error(format!("Other error: {e}"))
100 }
101}
102
103impl<E, R> From<SdkError<E, R>> for SignerError {
104 fn from(e: SdkError<E, R>) -> Self {
105 SignerError::other_error(format!("Other error: {e}"))
106 }
107}