fix(ecstore): refuse an empty azure account key at client build

This commit is contained in:
overtrue
2026-09-05 16:11:47 +08:00
parent b95f4a328b
commit 8f26458b8c
2 changed files with 50 additions and 6 deletions
@@ -91,11 +91,17 @@ impl AzureSourceBackend {
ca_cert_pem: Option<&str>,
) -> Result<Self, RemoteS3ClientError> {
let credential = match &spec.auth {
AzureAuth::SharedKey(key) => Credential::SharedKey(
base64_simd::STANDARD
AzureAuth::SharedKey(key) => {
let key = base64_simd::STANDARD
.decode_to_vec(key.as_bytes())
.map_err(|_| RemoteS3ClientError::Credentials("azure account key is not base64"))?,
),
.map_err(|_| RemoteS3ClientError::Credentials("azure account key is not base64"))?;
// HMAC accepts a zero-length key, so an absent one would sign
// every request with nothing rather than fail here.
if key.is_empty() {
return Err(RemoteS3ClientError::Credentials("azure account key is empty"));
}
Credential::SharedKey(key)
}
AzureAuth::Sas(sas) => {
let pairs: Vec<(String, String)> = url::form_urlencoded::parse(sas.trim_start_matches('?').as_bytes())
.into_owned()
@@ -705,6 +711,44 @@ mod tests {
]
}
#[test]
fn an_absent_or_malformed_account_key_is_refused_before_any_request() {
for key in ["", "not base64!"] {
let spec = AzureSourceSpec {
account: "acct".to_string(),
auth: AzureAuth::SharedKey(key.to_string()),
};
let built = AzureSourceBackend::new(
"https://acct.blob.core.windows.net",
"legacy",
&spec,
SourceTimeouts::default(),
false,
None,
);
assert!(
matches!(built, Err(RemoteS3ClientError::Credentials(_))),
"{key:?} must not build a client"
);
}
let spec = AzureSourceSpec {
account: "acct".to_string(),
auth: AzureAuth::Sas(String::new()),
};
assert!(
AzureSourceBackend::new(
"https://acct.blob.core.windows.net",
"legacy",
&spec,
SourceTimeouts::default(),
false,
None
)
.is_err(),
"an empty SAS token carries no parameters"
);
}
#[tokio::test]
async fn head_signs_the_request_and_maps_azure_metadata() {
let (endpoint, recorded) = scripted_server(vec![ScriptedResponse::new(200, blob_headers(), String::new())]).await;