Skip to main content

alien_bindings/providers/vault/
aws_parameter_store.rs

1use crate::error::{ErrorData, Result};
2use alien_aws_clients::ssm::{GetParameterRequest, PutParameterRequest, SsmApi, SsmClient};
3use alien_error::Context;
4use async_trait::async_trait;
5use std::sync::Arc;
6
7/// AWS SSM Parameter Store vault binding implementation.
8#[derive(Debug)]
9pub struct AwsParameterStoreVault {
10    client: Arc<SsmClient>,
11    vault_prefix: String,
12}
13
14impl AwsParameterStoreVault {
15    /// Create a new AWS SSM Parameter Store vault binding.
16    pub fn new(client: Arc<SsmClient>, vault_prefix: String) -> Self {
17        Self {
18            client,
19            vault_prefix,
20        }
21    }
22
23    /// Generate the full parameter name with vault prefix.
24    fn full_parameter_name(&self, secret_name: &str) -> String {
25        format!("{}-{}", self.vault_prefix, secret_name)
26    }
27}
28
29#[async_trait]
30impl crate::traits::Binding for AwsParameterStoreVault {}
31
32#[async_trait]
33impl crate::traits::Vault for AwsParameterStoreVault {
34    /// Get a secret value by name.
35    async fn get_secret(&self, secret_name: &str) -> Result<String> {
36        let full_name = self.full_parameter_name(secret_name);
37
38        let request = GetParameterRequest::builder()
39            .name(full_name.clone())
40            .with_decryption(true)
41            .build();
42
43        let response =
44            self.client
45                .get_parameter(request)
46                .await
47                .context(ErrorData::CloudPlatformError {
48                    message: format!("Failed to get parameter '{}'", full_name),
49                    resource_id: None,
50                })?;
51
52        let parameter = response.parameter.ok_or_else(|| {
53            alien_error::AlienError::new(ErrorData::CloudPlatformError {
54                message: format!("Parameter '{}' missing in response", full_name),
55                resource_id: None,
56            })
57        })?;
58
59        parameter.value.ok_or_else(|| {
60            alien_error::AlienError::new(ErrorData::CloudPlatformError {
61                message: format!("Parameter '{}' has no value", full_name),
62                resource_id: None,
63            })
64        })
65    }
66
67    /// Set a secret value using SecureString parameters.
68    async fn set_secret(&self, secret_name: &str, value: &str) -> Result<()> {
69        let full_name = self.full_parameter_name(secret_name);
70
71        let request = PutParameterRequest::builder()
72            .name(full_name.clone())
73            .value(value.to_string())
74            .parameter_type("SecureString".to_string())
75            .description(format!(
76                "Secret managed by Alien vault {}",
77                self.vault_prefix
78            ))
79            .overwrite(true)
80            .build();
81
82        self.client
83            .put_parameter(request)
84            .await
85            .context(ErrorData::CloudPlatformError {
86                message: format!("Failed to put parameter '{}'", full_name),
87                resource_id: None,
88            })?;
89
90        Ok(())
91    }
92
93    /// Delete a secret.
94    async fn delete_secret(&self, secret_name: &str) -> Result<()> {
95        let full_name = self.full_parameter_name(secret_name);
96
97        self.client
98            .delete_parameter(&full_name)
99            .await
100            .context(ErrorData::CloudPlatformError {
101                message: format!("Failed to delete parameter '{}'", full_name),
102                resource_id: None,
103            })?;
104
105        Ok(())
106    }
107}