@@ -6,6 +6,7 @@ use crate::{
6
6
AccountSharedAccessSignatureBuilder , ClientAccountSharedAccessSignature ,
7
7
} ,
8
8
} ;
9
+ use azure_core:: auth:: TokenCredential ;
9
10
use azure_core:: headers:: * ;
10
11
use azure_core:: HttpClient ;
11
12
use bytes:: Bytes ;
@@ -26,15 +27,29 @@ pub const EMULATOR_ACCOUNT: &str = "devstoreaccount1";
26
27
pub const EMULATOR_ACCOUNT_KEY : & str =
27
28
"Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" ;
28
29
30
+ pub const STORAGE_TOKEN_SCOPE : & str = "https://storage.azure.com/" ;
31
+
29
32
const HEADER_VERSION : & str = "x-ms-version" ;
30
33
31
34
const AZURE_VERSION : & str = "2019-12-12" ;
32
35
33
- #[ derive( Debug , Clone , PartialEq , Eq ) ]
34
36
pub enum StorageCredentials {
35
37
Key ( String , String ) ,
36
38
SASToken ( Vec < ( String , String ) > ) ,
37
39
BearerToken ( String ) ,
40
+ TokenCredential ( Box < dyn TokenCredential > ) ,
41
+ }
42
+
43
+ impl std:: fmt:: Debug for StorageCredentials {
44
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
45
+ match & self {
46
+ StorageCredentials :: TokenCredential ( _) => f
47
+ . debug_struct ( "StorageCredentials" )
48
+ . field ( "credential" , & "TokenCredential" )
49
+ . finish ( ) ,
50
+ _ => self . fmt ( f) ,
51
+ }
52
+ }
38
53
}
39
54
40
55
#[ derive( Debug , Clone , Copy ) ]
@@ -45,7 +60,7 @@ pub enum ServiceType {
45
60
Table ,
46
61
}
47
62
48
- #[ derive( Debug , Clone ) ]
63
+ #[ derive( Debug ) ]
49
64
pub struct StorageAccountClient {
50
65
storage_credentials : StorageCredentials ,
51
66
http_client : Arc < dyn HttpClient > ,
@@ -236,6 +251,36 @@ impl StorageAccountClient {
236
251
} )
237
252
}
238
253
254
+ pub fn new_token_credential < A > (
255
+ http_client : Arc < dyn HttpClient > ,
256
+ account : A ,
257
+ token_credential : Box < dyn TokenCredential > ,
258
+ ) -> Arc < Self >
259
+ where
260
+ A : Into < String > ,
261
+ {
262
+ let account = account. into ( ) ;
263
+
264
+ Arc :: new ( Self {
265
+ blob_storage_url : Url :: parse ( & format ! ( "https://{}.blob.core.windows.net" , & account) )
266
+ . unwrap ( ) ,
267
+ table_storage_url : Url :: parse ( & format ! ( "https://{}.table.core.windows.net" , & account) )
268
+ . unwrap ( ) ,
269
+ queue_storage_url : Url :: parse ( & format ! ( "https://{}.queue.core.windows.net" , & account) )
270
+ . unwrap ( ) ,
271
+ queue_storage_secondary_url : Url :: parse ( & format ! (
272
+ "https://{}-secondary.queue.core.windows.net" ,
273
+ & account
274
+ ) )
275
+ . unwrap ( ) ,
276
+ filesystem_url : Url :: parse ( & format ! ( "https://{}.dfs.core.windows.net" , & account) )
277
+ . unwrap ( ) ,
278
+ storage_credentials : StorageCredentials :: TokenCredential ( token_credential) ,
279
+ http_client,
280
+ account,
281
+ } )
282
+ }
283
+
239
284
pub fn new_connection_string (
240
285
http_client : Arc < dyn HttpClient > ,
241
286
connection_string : & str ,
@@ -407,6 +452,15 @@ impl StorageAccountClient {
407
452
StorageCredentials :: BearerToken ( token) => {
408
453
request. header ( AUTHORIZATION , format ! ( "Bearer {}" , token) )
409
454
}
455
+ StorageCredentials :: TokenCredential ( token_credential) => {
456
+ let bearer_token_future = token_credential. get_token ( STORAGE_TOKEN_SCOPE ) ;
457
+ let bearer_token = futures:: executor:: block_on ( bearer_token_future) ?;
458
+
459
+ request. header (
460
+ AUTHORIZATION ,
461
+ format ! ( "Bearer {}" , bearer_token. token. secret( ) ) ,
462
+ )
463
+ }
410
464
} ;
411
465
412
466
let request = if let Some ( request_body) = request_body {
0 commit comments