Skip to content

Commit c65a504

Browse files
committed
auth policy test updates
1 parent c3db2b7 commit c65a504

File tree

1 file changed

+112
-78
lines changed

1 file changed

+112
-78
lines changed

sdk/cosmosdb/azure_data_cosmos/src/authorization_policy.rs

Lines changed: 112 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -54,23 +54,6 @@ struct SignatureTarget<'a> {
5454
time_nonce: OffsetDateTime,
5555
}
5656

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-
7457
#[derive(Debug, Clone)]
7558
pub struct AuthorizationPolicy {
7659
credential: Credential,
@@ -109,7 +92,7 @@ impl Policy for AuthorizationPolicy {
10992

11093
let time_nonce = OffsetDateTime::now_utc();
11194

112-
let resource_link = generate_resource_link(request);
95+
let resource_link = extract_resource_link(request);
11396
let resource_type: &ResourceType = ctx
11497
.value()
11598
.expect("ResourceType must be in the Context at this point");
@@ -142,12 +125,12 @@ impl Policy for AuthorizationPolicy {
142125
/// four steps (with eager return):
143126
/// 1. Strip leading slash from the uri of the passed request.
144127
/// 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
146129
/// `ENDING_STRING`.
147130
/// 3. Find if the uri **is** the ending string (without the leading slash). If so return an empty
148131
/// string. This covers the exception of the rule above.
149132
/// 4. Return the received uri unchanged.
150-
fn generate_resource_link(request: &Request) -> String {
133+
fn extract_resource_link(request: &Request) -> String {
151134
static ENDING_STRINGS: &[&str] = &[
152135
"/dbs",
153136
"/colls",
@@ -283,19 +266,41 @@ fn string_to_sign(signature_target: SignatureTarget) -> String {
283266

284267
#[cfg(test)]
285268
mod tests {
269+
use azure_core::auth::AccessToken;
270+
use time::Duration;
271+
286272
use super::*;
287273

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+
288293
#[test]
289294
#[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+
});
299304
assert_eq!(
300305
ret,
301306
"get
@@ -309,111 +314,140 @@ mon, 01 jan 1900 01:00:00 gmt
309314

310315
#[tokio::test]
311316
#[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();
314350

315351
let auth_token = Credential::PrimaryKey(
316352
"8F8xXXOptJxkblM1DBXW7a6NMI5oE8NnwPGYBmwxLCKfejOK7B7yhcCHMGvN3PBrlMLIOeol1Hv9RCdzAZR5sg==".into(),
317-
)
318-
.unwrap();
353+
);
319354

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();
321357

322358
let ret = generate_authorization(
323359
&auth_token,
324360
&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+
},
331367
)
332368
.await
333369
.unwrap();
334370

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);
339377
}
340378

341379
#[tokio::test]
342380
#[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();
345383

346384
let auth_token = Credential::PrimaryKey(
347385
"dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5JiwvW0EndXdDku/dkKBp8/ufDToSxL".into(),
348-
)
349-
.unwrap();
386+
);
350387

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();
352390

353391
let ret = generate_authorization(
354392
&auth_token,
355393
&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+
},
362400
)
363401
.await
364402
.unwrap();
365403

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();
370408

371-
assert_eq!(
372-
ret,
373-
"type%3Dmaster%26ver%3D1.0%26sig%3DKvBM8vONofkv3yKm%2F8zD9MEGlbu6jjHDJBp4E9c2ZZI%3D"
374-
);
409+
assert_eq!(ret, expected);
375410
}
376411

377412
#[test]
378-
fn generate_resource_link_00() {
413+
fn extract_resource_link_specific_db() {
379414
let request = Request::new(
380-
Url::parse("https://.documents.azure.com/dbs/second").unwrap(),
415+
Url::parse("https://example.com/dbs/second").unwrap(),
381416
azure_core::Method::Get,
382417
);
383-
assert_eq!(&generate_resource_link(&request), "dbs/second");
418+
assert_eq!(&extract_resource_link(&request), "dbs/second");
384419
}
385420

386421
#[test]
387-
fn generate_resource_link_01() {
422+
fn extract_resource_link_dbs_root() {
388423
let request = Request::new(
389-
Url::parse("https://.documents.azure.com/dbs").unwrap(),
424+
Url::parse("https://example.com/dbs").unwrap(),
390425
azure_core::Method::Get,
391426
);
392-
assert_eq!(&generate_resource_link(&request), "");
427+
assert_eq!(&extract_resource_link(&request), "");
393428
}
394429

395430
#[test]
396-
fn generate_resource_link_02() {
431+
fn extract_resource_link_collection_nested() {
397432
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(),
399434
azure_core::Method::Get,
400435
);
401-
assert_eq!(&generate_resource_link(&request), "colls/second/third");
436+
assert_eq!(&extract_resource_link(&request), "colls/second/third");
402437
}
403438

404439
#[test]
405-
fn generate_resource_link_03() {
440+
fn extract_resource_link_collections_root() {
406441
let request = Request::new(
407442
Url::parse("https://.documents.azure.com/dbs/test_db/colls").unwrap(),
408443
azure_core::Method::Get,
409444
);
410-
assert_eq!(&generate_resource_link(&request), "dbs/test_db");
445+
assert_eq!(&extract_resource_link(&request), "dbs/test_db");
411446
}
412447

413448
#[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");
418452
}
419453
}

0 commit comments

Comments
 (0)