mongodb_atlas_cli/secrets/
mod.rs

1use crate::{
2    config::AuthType,
3    path::{GetCLICfgFilePathError, config_file},
4    secrets::{keyring::KeyringSecretStore, legacy::LegacySecretStore},
5};
6
7pub mod encoding;
8pub mod keyring;
9pub mod legacy;
10
11#[derive(thiserror::Error, Debug)]
12pub enum SecretStoreError {
13    #[error("Failed to get config file path: {0}")]
14    FailedToGetConfigFilePath(#[from] GetCLICfgFilePathError),
15    #[error("Key store unavailable: {reason}")]
16    KeyStoreUnavailable { reason: String },
17    #[error("Invalid key store format: {reason}")]
18    InvalidKeyStoreFormat { reason: String },
19    #[error("Failed to serialize key store: {reason}")]
20    Serialization { reason: String },
21}
22
23pub trait SecretStore {
24    fn get(
25        &self,
26        profile_name: &str,
27        auth_type: AuthType,
28    ) -> Result<Option<Secret>, SecretStoreError>;
29    fn set(&mut self, profile_name: &str, secret: Secret) -> Result<(), SecretStoreError>;
30    fn delete(&mut self, profile_name: &str) -> Result<(), SecretStoreError>;
31}
32
33pub fn get_secret_store() -> Result<Box<dyn SecretStore>, SecretStoreError> {
34    match KeyringSecretStore::new() {
35        Some(keyring_secret_store) => Ok(Box::new(keyring_secret_store) as Box<dyn SecretStore>),
36        None => Ok(Box::new(LegacySecretStore::new(config_file()?))),
37    }
38}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
41pub enum Secret {
42    ApiKeys(ApiKeys),
43    ServiceAccount(ServiceAccount),
44    UserAccount(UserAccount),
45}
46
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct ApiKeys {
49    pub private_api_key: String,
50    pub public_api_key: String,
51}
52
53impl ApiKeys {
54    pub fn new(public_api_key: String, private_api_key: String) -> Self {
55        Self {
56            public_api_key,
57            private_api_key,
58        }
59    }
60}
61
62impl From<ApiKeys> for Secret {
63    fn from(api_keys: ApiKeys) -> Self {
64        Secret::ApiKeys(api_keys)
65    }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
69pub struct ServiceAccount {
70    pub client_id: String,
71    pub client_secret: String,
72}
73
74impl ServiceAccount {
75    pub fn new(client_id: String, client_secret: String) -> Self {
76        Self {
77            client_id,
78            client_secret,
79        }
80    }
81}
82
83impl From<ServiceAccount> for Secret {
84    fn from(service_account: ServiceAccount) -> Self {
85        Secret::ServiceAccount(service_account)
86    }
87}
88
89#[derive(Debug, Clone, PartialEq, Eq)]
90pub struct UserAccount {
91    pub access_token: String,
92    pub refresh_token: String,
93}
94
95impl UserAccount {
96    pub fn new(access_token: String, refresh_token: String) -> Self {
97        Self {
98            access_token,
99            refresh_token,
100        }
101    }
102}
103
104impl From<UserAccount> for Secret {
105    fn from(user_account: UserAccount) -> Self {
106        Secret::UserAccount(user_account)
107    }
108}