reqsign_oracle/provide_credential/
env.rs1use crate::{Credential, constants::*};
19use reqsign_core::time::Timestamp;
20use reqsign_core::{Context, ProvideCredential, Result};
21use std::time::Duration;
22
23#[derive(Debug, Default, Clone)]
31pub struct EnvCredentialProvider {}
32
33impl EnvCredentialProvider {
34 pub fn new() -> Self {
36 Self {}
37 }
38}
39impl ProvideCredential for EnvCredentialProvider {
40 type Credential = Credential;
41
42 async fn provide_credential(&self, ctx: &Context) -> Result<Option<Self::Credential>> {
43 let envs = ctx.env_vars();
44
45 let user = envs.get(ORACLE_USER);
46 let tenancy = envs.get(ORACLE_TENANCY);
47 let key_file = envs.get(ORACLE_KEY_FILE);
48 let fingerprint = envs.get(ORACLE_FINGERPRINT);
49
50 match (user, tenancy, key_file, fingerprint) {
51 (Some(user), Some(tenancy), Some(key_file), Some(fingerprint)) => {
52 let expanded_key_file = if key_file.starts_with('~') {
54 ctx.expand_home_dir(key_file).ok_or_else(|| {
55 reqsign_core::Error::unexpected("Failed to expand home directory")
56 })?
57 } else {
58 key_file.clone()
59 };
60
61 Ok(Some(Credential {
62 user: user.clone(),
63 tenancy: tenancy.clone(),
64 key_file: expanded_key_file,
65 fingerprint: fingerprint.clone(),
66 expires_in: Some(Timestamp::now() + Duration::from_secs(600)),
67 }))
68 }
69 _ => Ok(None),
70 }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use reqsign_core::{OsEnv, StaticEnv};
78 use reqsign_file_read_tokio::TokioFileRead;
79 use reqsign_http_send_reqwest::ReqwestHttpSend;
80 use std::collections::HashMap;
81
82 #[tokio::test]
83 async fn test_env_credential_provider() -> anyhow::Result<()> {
84 let envs = HashMap::from([
85 (ORACLE_USER.to_string(), "test_user".to_string()),
86 (ORACLE_TENANCY.to_string(), "test_tenancy".to_string()),
87 (ORACLE_KEY_FILE.to_string(), "/path/to/key".to_string()),
88 (
89 ORACLE_FINGERPRINT.to_string(),
90 "test_fingerprint".to_string(),
91 ),
92 ]);
93
94 let ctx = Context::new()
95 .with_file_read(TokioFileRead)
96 .with_http_send(ReqwestHttpSend::default())
97 .with_env(OsEnv)
98 .with_env(StaticEnv {
99 home_dir: None,
100 envs,
101 });
102
103 let provider = EnvCredentialProvider::new();
104 let cred = provider.provide_credential(&ctx).await?;
105 assert!(cred.is_some());
106 let cred = cred.unwrap();
107 assert_eq!(cred.user, "test_user");
108 assert_eq!(cred.tenancy, "test_tenancy");
109 assert_eq!(cred.key_file, "/path/to/key");
110 assert_eq!(cred.fingerprint, "test_fingerprint");
111
112 Ok(())
113 }
114
115 #[tokio::test]
116 async fn test_env_credential_provider_missing_credentials() -> anyhow::Result<()> {
117 let ctx = Context::new()
118 .with_file_read(TokioFileRead)
119 .with_http_send(ReqwestHttpSend::default())
120 .with_env(OsEnv);
121
122 let provider = EnvCredentialProvider::new();
123 let cred = provider.provide_credential(&ctx).await?;
124 assert!(cred.is_none());
125
126 Ok(())
127 }
128
129 #[tokio::test]
130 async fn test_env_credential_provider_partial_credentials() -> anyhow::Result<()> {
131 let envs = HashMap::from([
133 (ORACLE_USER.to_string(), "test_user".to_string()),
134 (ORACLE_TENANCY.to_string(), "test_tenancy".to_string()),
135 ]);
136
137 let ctx = Context::new()
138 .with_file_read(TokioFileRead)
139 .with_http_send(ReqwestHttpSend::default())
140 .with_env(OsEnv)
141 .with_env(StaticEnv {
142 home_dir: None,
143 envs,
144 });
145
146 let provider = EnvCredentialProvider::new();
147 let cred = provider.provide_credential(&ctx).await?;
148 assert!(cred.is_none());
149
150 Ok(())
151 }
152
153 #[tokio::test]
154 async fn test_env_credential_provider_with_home_expansion() -> anyhow::Result<()> {
155 let envs = HashMap::from([
156 (ORACLE_USER.to_string(), "test_user".to_string()),
157 (ORACLE_TENANCY.to_string(), "test_tenancy".to_string()),
158 (ORACLE_KEY_FILE.to_string(), "~/key.pem".to_string()),
159 (
160 ORACLE_FINGERPRINT.to_string(),
161 "test_fingerprint".to_string(),
162 ),
163 ]);
164
165 let ctx = Context::new()
166 .with_file_read(TokioFileRead)
167 .with_http_send(ReqwestHttpSend::default())
168 .with_env(OsEnv)
169 .with_env(StaticEnv {
170 home_dir: Some("/home/user".into()),
171 envs,
172 });
173
174 let provider = EnvCredentialProvider::new();
175 let cred = provider.provide_credential(&ctx).await?;
176 assert!(cred.is_some());
177 let cred = cred.unwrap();
178 assert_eq!(cred.key_file, "/home/user/key.pem");
179
180 Ok(())
181 }
182}