@@ -54,23 +54,6 @@ struct SignatureTarget<'a> {
54
54
time_nonce : OffsetDateTime ,
55
55
}
56
56
57
- #[ cfg( feature = "key-auth" ) ]
58
- impl < ' a > SignatureTarget < ' a > {
59
- pub fn new (
60
- http_method : & ' a azure_core:: Method ,
61
- resource_type : & ' a ResourceType ,
62
- resource_link : & ' a str ,
63
- time_nonce : OffsetDateTime ,
64
- ) -> Self {
65
- SignatureTarget {
66
- http_method,
67
- resource_type,
68
- resource_link,
69
- time_nonce,
70
- }
71
- }
72
- }
73
-
74
57
#[ derive( Debug , Clone ) ]
75
58
pub struct AuthorizationPolicy {
76
59
credential : Credential ,
@@ -109,7 +92,7 @@ impl Policy for AuthorizationPolicy {
109
92
110
93
let time_nonce = OffsetDateTime :: now_utc ( ) ;
111
94
112
- let resource_link = generate_resource_link ( request) ;
95
+ let resource_link = extract_resource_link ( request) ;
113
96
let resource_type: & ResourceType = ctx
114
97
. value ( )
115
98
. expect ( "ResourceType must be in the Context at this point" ) ;
@@ -142,12 +125,12 @@ impl Policy for AuthorizationPolicy {
142
125
/// four steps (with eager return):
143
126
/// 1. Strip leading slash from the uri of the passed request.
144
127
/// 2. Find if the uri ends with a `ENDING_STRING`. If so, strip it and return. Every `ENDING_STRING`
145
- /// starts with a leading slash so this check will not match uri compsed **only** by the
128
+ /// starts with a leading slash so this check will not match uri composed **only** of the
146
129
/// `ENDING_STRING`.
147
130
/// 3. Find if the uri **is** the ending string (without the leading slash). If so return an empty
148
131
/// string. This covers the exception of the rule above.
149
132
/// 4. Return the received uri unchanged.
150
- fn generate_resource_link ( request : & Request ) -> String {
133
+ fn extract_resource_link ( request : & Request ) -> String {
151
134
static ENDING_STRINGS : & [ & str ] = & [
152
135
"/dbs" ,
153
136
"/colls" ,
@@ -283,19 +266,41 @@ fn string_to_sign(signature_target: SignatureTarget) -> String {
283
266
284
267
#[ cfg( test) ]
285
268
mod tests {
269
+ use azure_core:: auth:: AccessToken ;
270
+ use time:: Duration ;
271
+
286
272
use super :: * ;
287
273
274
+ #[ derive( Debug ) ]
275
+ struct TestTokenCredential ( String ) ;
276
+
277
+ #[ cfg_attr( target_arch = "wasm32" , async_trait:: async_trait( ?Send ) ) ]
278
+ #[ cfg_attr( not( target_arch = "wasm32" ) , async_trait:: async_trait) ]
279
+ impl TokenCredential for TestTokenCredential {
280
+ async fn get_token ( & self , scopes : & [ & str ] ) -> azure_core:: Result < AccessToken > {
281
+ let token = format ! ( "{}+{}" , self . 0 , scopes. join( "," ) ) ;
282
+ Ok ( AccessToken :: new (
283
+ token,
284
+ OffsetDateTime :: now_utc ( ) . saturating_add ( Duration :: minutes ( 5 ) ) ,
285
+ ) )
286
+ }
287
+
288
+ async fn clear_cache ( & self ) -> azure_core:: Result < ( ) > {
289
+ Ok ( ( ) )
290
+ }
291
+ }
292
+
288
293
#[ test]
289
294
#[ cfg( feature = "key-auth" ) ]
290
- fn string_to_sign_00 ( ) {
291
- let time = date:: parse_rfc3339 ( "1900-01-01T01:00:00.000000000+00:00" ) . unwrap ( ) ;
292
-
293
- let ret = string_to_sign ( SignatureTarget :: new (
294
- & azure_core:: Method :: Get ,
295
- & ResourceType :: Databases ,
296
- "dbs/MyDatabase/colls/MyCollection" ,
297
- time ,
298
- ) ) ;
295
+ fn string_to_sign_generates_expected_string_for_signing ( ) {
296
+ let time_nonce = date:: parse_rfc3339 ( "1900-01-01T01:00:00.000000000+00:00" ) . unwrap ( ) ;
297
+
298
+ let ret = string_to_sign ( SignatureTarget {
299
+ http_method : & azure_core:: Method :: Get ,
300
+ resource_type : & ResourceType :: Databases ,
301
+ resource_link : "dbs/MyDatabase/colls/MyCollection" ,
302
+ time_nonce ,
303
+ } ) ;
299
304
assert_eq ! (
300
305
ret,
301
306
"get
@@ -309,111 +314,140 @@ mon, 01 jan 1900 01:00:00 gmt
309
314
310
315
#[ tokio:: test]
311
316
#[ cfg( feature = "key-auth" ) ]
312
- async fn generate_authorization_00 ( ) {
313
- let time = date:: parse_rfc3339 ( "1900-01-01T01:00:00.000000000+00:00" ) . unwrap ( ) ;
317
+ async fn generate_authorization_for_token_credential ( ) {
318
+ let time_nonce = date:: parse_rfc3339 ( "1900-01-01T01:00:00.000000000+00:00" ) . unwrap ( ) ;
319
+ let cred = Arc :: new ( TestTokenCredential ( "test_token" . to_string ( ) ) ) ;
320
+ let auth_token = Credential :: Token ( cred) ;
321
+
322
+ // Use a fake URL since the actual endpoint URL is not important for this test
323
+ let url = Url :: parse ( "https://test_account.example.com/dbs/ToDoList" ) . unwrap ( ) ;
324
+
325
+ let ret = generate_authorization (
326
+ & auth_token,
327
+ & url,
328
+ SignatureTarget {
329
+ http_method : & azure_core:: Method :: Get ,
330
+ resource_type : & ResourceType :: Databases ,
331
+ resource_link : "dbs/MyDatabase/colls/MyCollection" ,
332
+ time_nonce,
333
+ } ,
334
+ )
335
+ . await
336
+ . unwrap ( ) ;
337
+
338
+ let expected: String = form_urlencoded:: byte_serialize (
339
+ b"type=aad&ver=1.0&sig=test_token+https://test_account.example.com/.default" ,
340
+ )
341
+ . collect ( ) ;
342
+
343
+ assert_eq ! ( ret, expected) ;
344
+ }
345
+
346
+ #[ tokio:: test]
347
+ #[ cfg( feature = "key-auth" ) ]
348
+ async fn generate_authorization_for_primary_key_0 ( ) {
349
+ let time_nonce = date:: parse_rfc3339 ( "1900-01-01T01:00:00.000000000+00:00" ) . unwrap ( ) ;
314
350
315
351
let auth_token = Credential :: PrimaryKey (
316
352
"8F8xXXOptJxkblM1DBXW7a6NMI5oE8NnwPGYBmwxLCKfejOK7B7yhcCHMGvN3PBrlMLIOeol1Hv9RCdzAZR5sg==" . into ( ) ,
317
- )
318
- . unwrap ( ) ;
353
+ ) ;
319
354
320
- let url = Url :: parse ( "https://.documents.azure.com/dbs/ToDoList" ) . unwrap ( ) ;
355
+ // Use a fake URL since the actual endpoint URL is not important for this test
356
+ let url = Url :: parse ( "https://test_account.example.com/dbs/ToDoList" ) . unwrap ( ) ;
321
357
322
358
let ret = generate_authorization (
323
359
& auth_token,
324
360
& url,
325
- SignatureTarget :: new (
326
- & azure_core:: Method :: Get ,
327
- & ResourceType :: Databases ,
328
- "dbs/MyDatabase/colls/MyCollection" ,
329
- time ,
330
- ) ,
361
+ SignatureTarget {
362
+ http_method : & azure_core:: Method :: Get ,
363
+ resource_type : & ResourceType :: Databases ,
364
+ resource_link : "dbs/MyDatabase/colls/MyCollection" ,
365
+ time_nonce ,
366
+ } ,
331
367
)
332
368
. await
333
369
. unwrap ( ) ;
334
370
335
- assert_eq ! (
336
- ret,
337
- "type%3Dmaster%26ver%3D1.0%26sig%3DQkz%2Fr%2B1N2%2BPEnNijxGbGB%2FADvLsLBQmZ7uBBMuIwf4I%3D"
338
- ) ;
371
+ let expected: String = form_urlencoded:: byte_serialize (
372
+ b"type=master&ver=1.0&sig=Qkz/r+1N2+PEnNijxGbGB/ADvLsLBQmZ7uBBMuIwf4I=" ,
373
+ )
374
+ . collect ( ) ;
375
+
376
+ assert_eq ! ( ret, expected) ;
339
377
}
340
378
341
379
#[ tokio:: test]
342
380
#[ cfg( feature = "key-auth" ) ]
343
- async fn generate_authorization_01 ( ) {
344
- let time = date:: parse_rfc3339 ( "2017-04-27T00:51:12.000000000+00:00" ) . unwrap ( ) ;
381
+ async fn generate_authorization_for_primary_key_1 ( ) {
382
+ let time_nonce = date:: parse_rfc3339 ( "2017-04-27T00:51:12.000000000+00:00" ) . unwrap ( ) ;
345
383
346
384
let auth_token = Credential :: PrimaryKey (
347
385
"dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5JiwvW0EndXdDku/dkKBp8/ufDToSxL" . into ( ) ,
348
- )
349
- . unwrap ( ) ;
386
+ ) ;
350
387
351
- let url = Url :: parse ( "https://.documents.azure.com/dbs/ToDoList" ) . unwrap ( ) ;
388
+ // Use a fake URL since the actual endpoint URL is not important for this test
389
+ let url = Url :: parse ( "https://test_account.example.com/dbs/ToDoList" ) . unwrap ( ) ;
352
390
353
391
let ret = generate_authorization (
354
392
& auth_token,
355
393
& url,
356
- SignatureTarget :: new (
357
- & azure_core:: Method :: Get ,
358
- & ResourceType :: Databases ,
359
- "dbs/ToDoList" ,
360
- time ,
361
- ) ,
394
+ SignatureTarget {
395
+ http_method : & azure_core:: Method :: Get ,
396
+ resource_type : & ResourceType :: Databases ,
397
+ resource_link : "dbs/ToDoList" ,
398
+ time_nonce ,
399
+ } ,
362
400
)
363
401
. await
364
402
. unwrap ( ) ;
365
403
366
- // This is the result shown in the MSDN page. It's clearly wrong :)
367
- // below is the correct one.
368
- //assert_eq!(ret,
369
- // "type%3dmaster%26ver%3d1.0%26sig%3dc09PEVJrgp2uQRkr934kFbTqhByc7TVr3O" );
404
+ let expected : String = form_urlencoded :: byte_serialize (
405
+ b"type=master&ver=1.0&sig=KvBM8vONofkv3yKm/8zD9MEGlbu6jjHDJBp4E9c2ZZI=" ,
406
+ )
407
+ . collect ( ) ;
370
408
371
- assert_eq ! (
372
- ret,
373
- "type%3Dmaster%26ver%3D1.0%26sig%3DKvBM8vONofkv3yKm%2F8zD9MEGlbu6jjHDJBp4E9c2ZZI%3D"
374
- ) ;
409
+ assert_eq ! ( ret, expected) ;
375
410
}
376
411
377
412
#[ test]
378
- fn generate_resource_link_00 ( ) {
413
+ fn extract_resource_link_specific_db ( ) {
379
414
let request = Request :: new (
380
- Url :: parse ( "https://.documents.azure .com/dbs/second" ) . unwrap ( ) ,
415
+ Url :: parse ( "https://example .com/dbs/second" ) . unwrap ( ) ,
381
416
azure_core:: Method :: Get ,
382
417
) ;
383
- assert_eq ! ( & generate_resource_link ( & request) , "dbs/second" ) ;
418
+ assert_eq ! ( & extract_resource_link ( & request) , "dbs/second" ) ;
384
419
}
385
420
386
421
#[ test]
387
- fn generate_resource_link_01 ( ) {
422
+ fn extract_resource_link_dbs_root ( ) {
388
423
let request = Request :: new (
389
- Url :: parse ( "https://.documents.azure .com/dbs" ) . unwrap ( ) ,
424
+ Url :: parse ( "https://example .com/dbs" ) . unwrap ( ) ,
390
425
azure_core:: Method :: Get ,
391
426
) ;
392
- assert_eq ! ( & generate_resource_link ( & request) , "" ) ;
427
+ assert_eq ! ( & extract_resource_link ( & request) , "" ) ;
393
428
}
394
429
395
430
#[ test]
396
- fn generate_resource_link_02 ( ) {
431
+ fn extract_resource_link_collection_nested ( ) {
397
432
let request = Request :: new (
398
- Url :: parse ( "https://.documents.azure .com/colls/second/third" ) . unwrap ( ) ,
433
+ Url :: parse ( "https://example .com/colls/second/third" ) . unwrap ( ) ,
399
434
azure_core:: Method :: Get ,
400
435
) ;
401
- assert_eq ! ( & generate_resource_link ( & request) , "colls/second/third" ) ;
436
+ assert_eq ! ( & extract_resource_link ( & request) , "colls/second/third" ) ;
402
437
}
403
438
404
439
#[ test]
405
- fn generate_resource_link_03 ( ) {
440
+ fn extract_resource_link_collections_root ( ) {
406
441
let request = Request :: new (
407
442
Url :: parse ( "https://.documents.azure.com/dbs/test_db/colls" ) . unwrap ( ) ,
408
443
azure_core:: Method :: Get ,
409
444
) ;
410
- assert_eq ! ( & generate_resource_link ( & request) , "dbs/test_db" ) ;
445
+ assert_eq ! ( & extract_resource_link ( & request) , "dbs/test_db" ) ;
411
446
}
412
447
413
448
#[ test]
414
- fn scope_from_url_01 ( ) {
415
- let scope =
416
- scope_from_url ( & Url :: parse ( "https://.documents.azure.com/dbs/test_db/colls" ) . unwrap ( ) ) ;
417
- assert_eq ! ( scope, "https://.documents.azure.com/.default" ) ;
449
+ fn scope_from_url_extracts_correct_scope ( ) {
450
+ let scope = scope_from_url ( & Url :: parse ( "https://example.com/dbs/test_db/colls" ) . unwrap ( ) ) ;
451
+ assert_eq ! ( scope, "https://example.com/.default" ) ;
418
452
}
419
453
}
0 commit comments