google_cloud_default/
lib.rs1use async_trait::async_trait;
13
14use google_cloud_auth::error::Error;
15
16#[async_trait]
17pub trait WithAuthExt {
18 async fn with_auth(mut self) -> Result<Self, Error>
19 where
20 Self: Sized;
21
22 async fn with_credentials(
23 self,
24 credentials: google_cloud_auth::credentials::CredentialsFile,
25 ) -> Result<Self, Error>
26 where
27 Self: Sized;
28}
29
30#[cfg(feature = "pubsub")]
31#[async_trait]
32impl WithAuthExt for google_cloud_pubsub::client::ClientConfig {
33 async fn with_auth(mut self) -> Result<Self, Error> {
34 if let google_cloud_gax::conn::Environment::GoogleCloud(_) = self.environment {
35 let ts = google_cloud_auth::token::DefaultTokenSourceProvider::new(google_cloud_auth::project::Config {
36 audience: Some(google_cloud_pubsub::apiv1::conn_pool::AUDIENCE),
37 scopes: Some(&google_cloud_pubsub::apiv1::conn_pool::SCOPES),
38 sub: None,
39 })
40 .await?;
41 self.project_id = ts.project_id.clone();
42 self.environment = google_cloud_gax::conn::Environment::GoogleCloud(Box::new(ts))
43 }
44 Ok(self)
45 }
46
47 async fn with_credentials(
48 mut self,
49 credentials: google_cloud_auth::credentials::CredentialsFile,
50 ) -> Result<Self, Error> {
51 if let google_cloud_gax::conn::Environment::GoogleCloud(_) = self.environment {
52 let ts = google_cloud_auth::token::DefaultTokenSourceProvider::new_with_credentials(
53 google_cloud_auth::project::Config {
54 audience: Some(google_cloud_pubsub::apiv1::conn_pool::AUDIENCE),
55 scopes: Some(&google_cloud_pubsub::apiv1::conn_pool::SCOPES),
56 sub: None,
57 },
58 Box::new(credentials),
59 )
60 .await?;
61 self.project_id = ts.project_id.clone();
62 self.environment = google_cloud_gax::conn::Environment::GoogleCloud(Box::new(ts))
63 }
64
65 Ok(self)
66 }
67}
68
69#[cfg(feature = "spanner")]
70#[async_trait]
71impl WithAuthExt for google_cloud_spanner::client::ClientConfig {
72 async fn with_auth(mut self) -> Result<Self, Error> {
73 if let google_cloud_gax::conn::Environment::GoogleCloud(_) = self.environment {
74 let ts = google_cloud_auth::token::DefaultTokenSourceProvider::new(google_cloud_auth::project::Config {
75 audience: Some(google_cloud_spanner::apiv1::conn_pool::AUDIENCE),
76 scopes: Some(&google_cloud_spanner::apiv1::conn_pool::SCOPES),
77 sub: None,
78 })
79 .await?;
80 self.environment = google_cloud_gax::conn::Environment::GoogleCloud(Box::new(ts))
81 }
82 Ok(self)
83 }
84
85 async fn with_credentials(
86 mut self,
87 credentials: google_cloud_auth::credentials::CredentialsFile,
88 ) -> Result<Self, Error> {
89 if let google_cloud_gax::conn::Environment::GoogleCloud(_) = self.environment {
90 let ts = google_cloud_auth::token::DefaultTokenSourceProvider::new_with_credentials(
91 google_cloud_auth::project::Config {
92 audience: Some(google_cloud_spanner::apiv1::conn_pool::AUDIENCE),
93 scopes: Some(&google_cloud_spanner::apiv1::conn_pool::SCOPES),
94 sub: None,
95 },
96 Box::new(credentials),
97 )
98 .await?;
99 self.environment = google_cloud_gax::conn::Environment::GoogleCloud(Box::new(ts))
100 }
101 Ok(self)
102 }
103}
104
105#[cfg(feature = "storage")]
106#[async_trait]
107impl WithAuthExt for google_cloud_storage::client::ClientConfig {
108 async fn with_auth(mut self) -> Result<Self, Error> {
109 let ts = google_cloud_auth::token::DefaultTokenSourceProvider::new(google_cloud_auth::project::Config {
110 audience: None,
111 scopes: Some(&google_cloud_storage::http::storage_client::SCOPES),
112 sub: None,
113 })
114 .await?;
115
116 match &ts.source_credentials {
117 Some(cred) => {
119 self.project_id = cred.project_id.clone();
120 if let Some(pk) = &cred.private_key {
121 self.default_sign_by =
122 Some(google_cloud_storage::sign::SignBy::PrivateKey(pk.clone().into_bytes()));
123 }
124 self.default_google_access_id = cred.client_email.clone();
125 }
126 None => {
128 self.project_id = Some(google_cloud_metadata::project_id().await);
129 self.default_sign_by = Some(google_cloud_storage::sign::SignBy::SignBytes);
130 self.default_google_access_id = google_cloud_metadata::email("default").await.ok();
131 }
132 }
133
134 self.token_source_provider = Box::new(ts);
135 Ok(self)
136 }
137
138 async fn with_credentials(
139 mut self,
140 credentials: google_cloud_auth::credentials::CredentialsFile,
141 ) -> Result<Self, Error> {
142 let ts = google_cloud_auth::token::DefaultTokenSourceProvider::new_with_credentials(
143 google_cloud_auth::project::Config {
144 audience: None,
145 scopes: Some(&google_cloud_storage::http::storage_client::SCOPES),
146 sub: None,
147 },
148 Box::new(credentials),
149 )
150 .await?;
151
152 match &ts.source_credentials {
153 Some(cred) => {
155 self.project_id = cred.project_id.clone();
156 if let Some(pk) = &cred.private_key {
157 self.default_sign_by =
158 Some(google_cloud_storage::sign::SignBy::PrivateKey(pk.clone().into_bytes()));
159 }
160 self.default_google_access_id = cred.client_email.clone();
161 }
162 None => {
164 self.project_id = Some(google_cloud_metadata::project_id().await);
165 self.default_sign_by = Some(google_cloud_storage::sign::SignBy::SignBytes);
166 self.default_google_access_id = google_cloud_metadata::email("default").await.ok();
167 }
168 }
169
170 self.token_source_provider = Box::new(ts);
171 Ok(self)
172 }
173}
174
175#[cfg(feature = "bigquery")]
176pub mod bigquery {
177 use async_trait::async_trait;
178 use google_cloud_auth::credentials::CredentialsFile;
179 use google_cloud_auth::error::Error;
180 use google_cloud_auth::project::Config;
181 use google_cloud_auth::token::DefaultTokenSourceProvider;
182 use google_cloud_bigquery::client::ClientConfig;
183
184 #[async_trait]
185 pub trait CreateAuthExt {
186 async fn new_with_auth() -> Result<(Self, Option<String>), Error>
187 where
188 Self: Sized;
189
190 async fn new_with_credentials(credentials: CredentialsFile) -> Result<(Self, Option<String>), Error>
191 where
192 Self: Sized;
193 }
194
195 #[async_trait]
196 impl CreateAuthExt for ClientConfig {
197 async fn new_with_auth() -> Result<(Self, Option<String>), Error> {
198 let ts_http = DefaultTokenSourceProvider::new(bigquery_http_auth_config()).await?;
199 let ts_grpc = DefaultTokenSourceProvider::new(bigquery_grpc_auth_config()).await?;
200 let project_id = ts_grpc.project_id.clone();
201 let config = Self::new(Box::new(ts_http), Box::new(ts_grpc));
202 Ok((config, project_id))
203 }
204 async fn new_with_credentials(credentials: CredentialsFile) -> Result<(Self, Option<String>), Error>
205 where
206 Self: Sized,
207 {
208 let ts_http = DefaultTokenSourceProvider::new_with_credentials(
209 bigquery_http_auth_config(),
210 Box::new(credentials.clone()),
211 )
212 .await?;
213 let ts_grpc =
214 DefaultTokenSourceProvider::new_with_credentials(bigquery_grpc_auth_config(), Box::new(credentials))
215 .await?;
216 let project_id = ts_grpc.project_id.clone();
217 let config = Self::new(Box::new(ts_http), Box::new(ts_grpc));
218 Ok((config, project_id))
219 }
220 }
221
222 #[cfg(feature = "bigquery")]
223 fn bigquery_http_auth_config() -> Config<'static> {
224 Config {
225 audience: None,
226 scopes: Some(&google_cloud_bigquery::http::bigquery_client::SCOPES),
227 sub: None,
228 }
229 }
230
231 #[cfg(feature = "bigquery")]
232 fn bigquery_grpc_auth_config() -> Config<'static> {
233 Config {
234 audience: Some(google_cloud_bigquery::grpc::apiv1::conn_pool::AUDIENCE),
235 scopes: Some(&google_cloud_bigquery::grpc::apiv1::conn_pool::SCOPES),
236 sub: None,
237 }
238 }
239}
240
241#[cfg(test)]
242mod test {
243 use google_cloud_gax::conn::Environment;
244
245 use crate::WithAuthExt;
246
247 #[tokio::test]
248 async fn test_spanner() {
249 let config = google_cloud_spanner::client::ClientConfig::default()
250 .with_auth()
251 .await
252 .unwrap();
253 if let Environment::Emulator(_) = config.environment {
254 unreachable!()
255 }
256 }
257
258 #[tokio::test]
259 async fn test_pubsub() {
260 let config = google_cloud_pubsub::client::ClientConfig::default()
261 .with_auth()
262 .await
263 .unwrap();
264 if let Environment::Emulator(_) = config.environment {
265 unreachable!()
266 }
267 }
268
269 #[tokio::test]
270 async fn test_storage() {
271 let config = google_cloud_storage::client::ClientConfig::default()
272 .with_auth()
273 .await
274 .unwrap();
275 assert!(config.default_google_access_id.is_some());
276 assert!(config.default_sign_by.is_some());
277 }
278
279 #[tokio::test]
280 async fn test_bigquery() {
281 use crate::bigquery::CreateAuthExt;
282 let (_config, project_id) = google_cloud_bigquery::client::ClientConfig::new_with_auth()
283 .await
284 .unwrap();
285 assert!(project_id.is_some())
286 }
287}