1use std::sync::Arc;
2
3use futures::future::BoxFuture;
4
5use crate::service::make_service;
6use crate::token::TemporaryToken;
7use crate::{ClientOptions, CredentialProvider, RequestSigner, Result, RetryConfig, TokenProvider};
8
9mod builder;
10pub(crate) mod credential;
11mod sas;
12
13pub(crate) use self::credential::*;
14pub use builder::*;
15pub use credential::AzureCredential;
16pub use sas::{DEFAULT_TTL_SECS, generate_storage_key_sas, generate_user_delegation_sas};
17
18pub type AzureCredentialProvider = Arc<dyn CredentialProvider<Credential = AzureCredential>>;
19
20#[derive(Debug, Clone)]
22pub struct AzureConfig {
23 pub credentials: AzureCredentialProvider,
24 pub retry_config: RetryConfig,
25 pub skip_signature: bool,
26 pub client_options: ClientOptions,
27}
28
29impl AzureConfig {
30 pub(crate) async fn get_credential(&self) -> Result<Option<Arc<AzureCredential>>> {
31 if self.skip_signature {
32 Ok(None)
33 } else {
34 Some(self.credentials.get_credential().await).transpose()
35 }
36 }
37}
38
39impl RequestSigner for AzureConfig {
40 fn sign<'a>(
41 &'a self,
42 req: reqwest::RequestBuilder,
43 ) -> BoxFuture<'a, Result<reqwest::RequestBuilder>> {
44 Box::pin(async move {
45 let credential = self.get_credential().await?;
46 Ok(req.with_azure_authorization(&credential))
47 })
48 }
49}
50
51pub async fn fetch_client_secret_token(
60 tenant_id: &str,
61 client_id: String,
62 client_secret: String,
63 authority_host: Option<String>,
64) -> Result<TemporaryToken<Arc<AzureCredential>>> {
65 let provider = ClientSecretOAuthProvider::new_with_scope(
66 client_id,
67 client_secret,
68 tenant_id,
69 authority_host,
70 credential::AZURE_STORAGE_SCOPE,
71 );
72 let client = ClientOptions::default().client()?;
73 let service = make_service(client.clone(), None);
74 provider
75 .fetch_token(&client, &service, &RetryConfig::default())
76 .await
77}
78
79pub async fn fetch_workload_identity_token(
84 tenant_id: &str,
85 client_id: String,
86 federated_token_file: String,
87 authority_host: Option<String>,
88) -> Result<TemporaryToken<Arc<AzureCredential>>> {
89 let provider = WorkloadIdentityOAuthProvider::new(
90 client_id,
91 federated_token_file,
92 tenant_id,
93 authority_host,
94 );
95 let client = ClientOptions::default().client()?;
96 let service = make_service(client.clone(), None);
97 provider
98 .fetch_token(&client, &service, &RetryConfig::default())
99 .await
100}
101
102pub async fn fetch_managed_identity_token(
108 client_id: Option<String>,
109 object_id: Option<String>,
110 msi_res_id: Option<String>,
111) -> Result<TemporaryToken<Arc<AzureCredential>>> {
112 let provider = ImdsManagedIdentityProvider::new(client_id, object_id, msi_res_id, None);
113 let client = ClientOptions::default().with_allow_http(true).client()?;
114 let service = make_service(client.clone(), None);
115 provider
116 .fetch_token(&client, &service, &RetryConfig::default())
117 .await
118}