Code Monkey home page Code Monkey logo

Comments (6)

fafhrd91 avatar fafhrd91 commented on August 26, 2024

according to spec it is Connection authentication failed due to a system error.

you can enable trace logging, it may give more info

from ntex-amqp.

calebroelenshowest avatar calebroelenshowest commented on August 26, 2024

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
image
This is probably a misconfiguration on my part.
So one more question:
image
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.

image

Thx in advance for any replies :)

Update: I will be messaging Azure over this issue, I will post the solution if I find it.

from ntex-amqp.

calebroelenshowest avatar calebroelenshowest commented on August 26, 2024

Posted an issue on Azure: Link

from ntex-amqp.

fafhrd91 avatar fafhrd91 commented on August 26, 2024

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)

from ntex-amqp.

calebroelenshowest avatar calebroelenshowest commented on August 26, 2024

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 👍 .

from ntex-amqp.

calebroelenshowest avatar calebroelenshowest commented on August 26, 2024

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

from ntex-amqp.

Related Issues (8)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.