Skip to content
This repository was archived by the owner on Oct 6, 2020. It is now read-only.

Commit d3d9973

Browse files
authored
Merge pull request #111 from aerys/feature/add-sas-auth
Add support for SAS token based authentication (#110).
2 parents c13a9a0 + 1c892c0 commit d3d9973

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

src/azure/storage/client.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub trait Container {
4646
pub struct Client {
4747
account: String,
4848
key: String,
49+
sas_token: Option<Vec<(String, String)>>,
4950
hc: hyper::Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>,
5051
blob_uri: String,
5152
table_uri: String,
@@ -176,12 +177,34 @@ impl Client {
176177
Client::azure(account, key)
177178
}
178179

180+
pub fn azure_sas(account: &str, sas_token: &str) -> Result<Client, AzureError> {
181+
let client = hyper::Client::builder().build(hyper_tls::HttpsConnector::new(4)?);
182+
let params: Vec<(String, String)> = Url::options()
183+
// Any base url will do: we just need to parse the SAS token
184+
// to get its query pairs.
185+
.base_url(Some(&Url::parse("https://blob.core.windows.net").unwrap()))
186+
.parse(sas_token).unwrap()
187+
.query_pairs()
188+
.map(|p| (String::from(p.0), String::from(p.1)))
189+
.collect();
190+
191+
Ok(Client {
192+
account: account.to_owned(),
193+
key: String::new(),
194+
sas_token: Some(params),
195+
hc: client,
196+
blob_uri: format!("https://{}.blob.core.windows.net", account),
197+
table_uri: format!("https://{}.table.core.windows.net", account),
198+
})
199+
}
200+
179201
pub fn azure(account: &str, key: &str) -> Result<Client, AzureError> {
180202
let client = hyper::Client::builder().build(hyper_tls::HttpsConnector::new(4)?);
181203

182204
Ok(Client {
183205
account: account.to_owned(),
184206
key: key.to_owned(),
207+
sas_token: None,
185208
hc: client,
186209
blob_uri: format!("https://{}.blob.core.windows.net", account),
187210
table_uri: format!("https://{}.table.core.windows.net", account),
@@ -199,6 +222,7 @@ impl Client {
199222
Ok(Client {
200223
account: "devstoreaccount1".to_owned(),
201224
key: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==".to_owned(),
225+
sas_token: None,
202226
hc: client,
203227
blob_uri,
204228
table_uri,
@@ -223,6 +247,13 @@ impl Client {
223247
&self.table_uri
224248
}
225249

250+
fn add_sas_token_to_uri(&self, uri: &str) -> String {
251+
match &self.sas_token {
252+
Some(token) => Url::parse_with_params(uri, token).unwrap().to_string(),
253+
None => String::from(uri),
254+
}
255+
}
256+
226257
pub(crate) fn perform_request<F>(
227258
&self,
228259
uri: &str,
@@ -233,7 +264,9 @@ impl Client {
233264
where
234265
F: FnOnce(&mut ::http::request::Builder),
235266
{
236-
perform_request(&self.hc, uri, method, &self.key, headers_func, request_body, ServiceType::Blob)
267+
let uri = self.add_sas_token_to_uri(uri);
268+
269+
perform_request(&self.hc, &uri, method, &self.key, headers_func, request_body, ServiceType::Blob)
237270
}
238271

239272
pub(crate) fn perform_table_request<F>(
@@ -247,9 +280,14 @@ impl Client {
247280
F: FnOnce(&mut ::http::request::Builder),
248281
{
249282
debug!("segment: {}, method: {:?}", segment, method,);
283+
284+
let uri = self.add_sas_token_to_uri(
285+
(self.get_uri_prefix(ServiceType::Table) + segment).as_str()
286+
);
287+
250288
perform_request(
251289
&self.hc,
252-
(self.get_uri_prefix(ServiceType::Table) + segment).as_str(),
290+
&uri,
253291
method,
254292
&self.key,
255293
headers_func,

src/azure/storage/rest_client.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,12 @@ where
274274
let b = request_body.map(|v| Vec::from(v).into()).unwrap_or_else(hyper::Body::empty);
275275
let mut request = request.body(b)?;
276276

277-
let auth = generate_authorization(request.headers(), &url, http_method, azure_key, service_type);
278-
request.headers_mut().insert(header::AUTHORIZATION, format_header_value(auth)?);
277+
// We sign the request only if it is not already signed (with the signature of an
278+
// SAS token for example)
279+
if url.query_pairs().find(|p| p.0 == "sig").is_none() {
280+
let auth = generate_authorization(request.headers(), &url, http_method, azure_key, service_type);
281+
request.headers_mut().insert(header::AUTHORIZATION, format_header_value(auth)?);
282+
}
279283

280284
Ok(client.request(request))
281285
}

0 commit comments

Comments
 (0)