Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rustcloud/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ gcloud-sdk = "0.24.7"
gcp_auth = "0.12.2"
hmac = "0.12.1"
mockall = "=0.9.1"
reqwest = "0.12.5"
rustls = { version = "0.23", features = ["ring"] }
reqwest = { version = "0.12.5", features = ["json"] }
serde = "1.0.203"
serde_json = "1.0.118"
sha2 = "0.10.9"
Expand Down
63 changes: 0 additions & 63 deletions rustcloud/src/azure/azure_apis/auth/azure_auth.rs

This file was deleted.

34 changes: 34 additions & 0 deletions rustcloud/src/azure/azure_apis/auth/azure_cli_auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use serde::Deserialize;
use std::process::Command;

#[derive(Debug, Deserialize)]
struct AzureToken {
accessToken: String,
}

pub struct AzureCliAuth;

impl AzureCliAuth {
pub fn get_token() -> Result<String, Box<dyn std::error::Error>> {
let output = Command::new("az.cmd")
.args([
"account",
"get-access-token",
"--resource",
"https://management.azure.com/",
"--output",
"json",
])
.output()?;

if !output.status.success() {
return Err("Failed to get Azure CLI token".into());
}

let json = String::from_utf8(output.stdout)?;

let token: AzureToken = serde_json::from_str(&json)?;

Ok(token.accessToken)
}
}
90 changes: 90 additions & 0 deletions rustcloud/src/azure/azure_apis/auth/azure_storage_auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use base64::{engine::general_purpose, Engine};
use chrono::Utc;
use hmac::{Hmac, Mac};
use sha2::Sha256;
use std::env;

type HmacSha256 = Hmac<Sha256>;

pub struct AzureStorageAuth;

impl AzureStorageAuth {
pub fn generate_headers(
method: &str,
account: &str,
resource: &str,
content_length: Option<usize>,
extra_headers: Option<Vec<(&str, &str)>>,
) -> (String, String) {
let key = env::var("AZURE_STORAGE_KEY").expect("AZURE_STORAGE_KEY not set");

let date = Utc::now().format("%a, %d %b %Y %H:%M:%S GMT").to_string();

let mut path = resource.to_string();
let mut query = String::new();

if let Some(pos) = resource.find('?') {
path = resource[..pos].to_string();
query = resource[pos + 1..].to_string();
}

let mut headers: Vec<(String, String)> = vec![
("x-ms-date".to_string(), date.clone()),
("x-ms-version".to_string(), "2020-10-02".to_string()),
];

if let Some(extra) = extra_headers {
for (k, v) in extra {
headers.push((k.to_lowercase(), v.to_string()));
}
}

headers.sort_by(|a, b| a.0.cmp(&b.0));

let canonical_headers = headers
.iter()
.map(|(k, v)| format!("{}:{}", k, v))
.collect::<Vec<String>>()
.join("\n");

let canonicalized_resource = if query.is_empty() {
format!("/{}{}", account, path)
} else {
let mut params: Vec<&str> = query.split('&').collect();
params.sort();

let query_string = params
.iter()
.map(|p| {
let kv: Vec<&str> = p.split('=').collect();
format!("{}:{}", kv[0].to_lowercase(), kv[1])
})
.collect::<Vec<String>>()
.join("\n");

format!("/{}{}\n{}", account, path, query_string)
};

let content_length_str = match content_length {
Some(len) if len > 0 => len.to_string(),
_ => "".to_string(),
};

let string_to_sign = format!(
"{}\n\n\n{}\n\n\n\n\n\n\n\n\n{}\n{}",
method, content_length_str, canonical_headers, canonicalized_resource
);

let decoded_key = general_purpose::STANDARD.decode(key).unwrap();

let mut mac = HmacSha256::new_from_slice(&decoded_key).unwrap();

mac.update(string_to_sign.as_bytes());

let signature = general_purpose::STANDARD.encode(mac.finalize().into_bytes());

let auth_header = format!("SharedKey {}:{}", account, signature);

(auth_header, date)
}
}
3 changes: 2 additions & 1 deletion rustcloud/src/azure/azure_apis/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod azure_auth;
pub mod azure_storage_auth;
pub mod azure_cli_auth;
Loading