Closed calebroelenshowest closed 2 years ago
according to spec it is Connection authentication failed due to a system error.
you can enable trace logging, it may give more info
Thx for the quick response.
Enabling tracing did not really show much more, so I added a few more traces.
-> The Sasl Outcome seems to return the SASL sys error.
Location: connector.rs, line 400-410
This is probably a misconfiguration on my part.
So one more question:
If the URL azure iot hub requests is of the following format:
-> 'amqps://username:sas_token@hostname/operation'
How do you translate it in all the params. Im just not sure about what the 'authz_id' param means.
One last note, is that I'm using an older version, because ntex-amqp doesn't build the v6 version.
Thx in advance for any replies :)
Update: I will be messaging Azure over this issue, I will post the solution if I find it.
Posted an issue on Azure: Link
authn_id
should be set to key name
password
is key itself,
let auth = ntex_amqp::client::SaslAuth {
authz_id: ByteString::from_static(""),
authn_id: key_name,
password: key,
};
let mut c = ntex_amqp::client::Connector();
c.hostname(hostname);
c.connect_sasl(hostname, auth)
Thx for the reply. I have tried a few options, and will now wait for a reply on Azure & Discord. I will post the solution here if I find the solution. This more a problem with Azures unclear docs :(. I will keep the issue open for now so I can post the solution later.
Thx for your time, have a good day 👍 .
I just found the solution to the problem, so here is the solution (I was quite stupid actually :p)
The problem is a combination of Azure and my code. The url_encode is not needed. Also, Access keys generated on Azure use the wrong signature. I found this out by sniffing through the python code.
This is the final code, which can successfully connect 👍
You can generate the correct SAS token with this: ` pub mod azureiothub { use std::fmt::Error; use std::ops::Add; use chrono::Duration; use hmac::{Hmac, Mac, NewMac}; use log::trace; use sha2::Sha256; use base64;
// Azure Iot Hub
pub struct Client{
// The azure client
}
impl Client{
// The client methods
}
pub enum GenSasTokenException{
DECODEBASE64,
INVALIDKEYLENGTH,
}
pub fn hostname(iot_hub_name: String) -> String{
format!("{}.azure-devices.net", iot_hub_name)
}
pub fn generate_sas_token(key: String, device_id: String, hub_name: String, validity_days: i64) -> Result<String, GenSasTokenException>{
// Generate a VALID SAS token
// Recoded from the rust azure SDK (mqtt) and the generate_sas_token function (Python SDK)
let b64_key = base64::decode(&key);
if b64_key.is_err(){
// Failed to decode
trace!("Failed to decode base64 key.");
return Err(GenSasTokenException::DECODEBASE64)
}
// Continue
// Is the key the right length?
let check_hmac = Hmac::<Sha256>::new_from_slice(&b64_key.unwrap());
if check_hmac.is_err(){
// Failed the length
trace!("The length of the key is invalid.");
return Err(GenSasTokenException::INVALIDKEYLENGTH)
}
// Continue
// Create the expire date.
let mut time_now = chrono::offset::Utc::now();
// Add the amount of days
let mut add_days = Duration::days(validity_days);
let mut time_now_plus_day = time_now.add(add_days);
// Now lets generate the token.
let expiry_timestamp = time_now_plus_day.timestamp();
let hub_url = format!("{}.azure-devices.net%2Fdevices%2F{}", hub_name, device_id);
// Coded to_sign
let to_sign = format!("{}\n{}", &hub_url, &expiry_timestamp);
println!("{}", to_sign);
// Safe to unwrap --> Check before
let unwrapped_key = base64::decode(&key).unwrap();
// Start generation
let mut mac = Hmac::<Sha256>::new_from_slice(&unwrapped_key).unwrap();
// SIGN GEN
mac.update(to_sign.as_bytes());
let mac_result = mac.finalize();
let signature = base64::encode(mac_result.into_bytes());
let pairs = &vec![("sig", signature)];
let token_result = serde_urlencoded::to_string(pairs).unwrap();
// Build up token signature
let full_token = format!(
"SharedAccessSignature sr={}.azure-devices.net%2Fdevices%2F{}&{}&se={}&skn={}",
hub_name,
device_id,
token_result,
expiry_timestamp,
device_id
);
return Ok(full_token)
}
}
mod test { use std::process::exit; use crate::azureiothub::generate_sas_token;
#[test]
fn gen_token(){
let token = generate_sas_token(String::from("PrimairyKeyHere"),
String::from("devicename"),
String::from("hubname"), 365);
if token.is_err(){
println!("Failed");
exit(1);
}
else {
println!("Token: {}", token.unwrap_or(String::from("")));
}
}
}`
The correct code to connect is this :
`let auth = ntex_amqp::client::SaslAuth { authz_id: ByteString::from_static(""), authn_id: authenticator_id.into(), password: password.into() };
let mut driver = client::Connector::new()
.connector(RustlsConnector::new(Arc::new(tls_config)));
driver.hostname(hostname);
let result = driver.connect_sasl(address, auth).await;
` This code will work for Azure Iot Hub, with TLS 1.2
On trying to connect with Azure Iot hub, I get the Sasl exception: SaslCode::Sys What does this error code mean?