Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MQTT connection to AWS IoT with Rpi0 #566

Closed
MAkcanca opened this issue Nov 29, 2020 · 6 comments
Closed

MQTT connection to AWS IoT with Rpi0 #566

MAkcanca opened this issue Nov 29, 2020 · 6 comments

Comments

@MAkcanca
Copy link

Environment

  • Elixir version: Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [hipe]
  • Nerves environment: rpi0

Current behavior

I'm trying to create an example project with AWS IoT Core, and it's supposed to just connect to the MQTT server and send hello world message, using the tortoise library. I even did a code search on whole github but couldn't find a proper working example. I believe AWS IoT and Nerves could have a happy marriage but it's really hard to bring them together (at least for me).
I wrote a simple connection function using the resources(error questions) I found from here and there. This code hangs, probably due to SSL keychain, depth, hostname_check, sni or other mambo jambo. I tried certifi.cacerts, certifi.cacertsfile etc but had no success. Is it really that hard to just send a Hello World message to an AWS IoT MQTT server using Nerves?

        client_opts = [ 
            client_id: "testdev01",
            handler: {Tortoise.Handler.Logger, []},
            server: {Tortoise.Transport.SSL,
            cacerts: :certifi.cacerts(),
            certfile: "/srv/erlang/lib/network_led-0.1.0/priv/testdev01.cert",
            keyfile: "/srv/erlang/lib/network_led-0.1.0/priv/testdev01.private.key",
            depth: 99,
            host: 'axxxxxxxxxx-ats.iot.eu-central-1.amazonaws.com',
            port: 8883,
            customize_hostname_check: [match_fun: :public_key.pkix_verify_hostname_match_fun(:https)],
            versions: [:'tlsv1.2'],
            server_name_indication: '*.iot.eu-central-1.amazonaws.com',
            },
            subscriptions: [{"#", 0}]
        ]
        Tortoise.Connection.start_link(client_opts)
        Tortoise.publish("testdev01", "sensor/test", "hello")

Expected behavior

It should publish the MQTT message with proper settings. An example implementation could help a lot.

I also raised this issue on Tortoise library. gausby/tortoise#127

Thanks a lot.

@fhunleth
Copy link
Member

@MAkcanca - You're not alone. MQTT to AWS IoT is surprisingly hard to debug. It's not really the MQTT part, but getting the SSL part right. My company has been working with @gausby to try to make this easier by adding a library around Tortoise called Jackalope. See https://github.com/smartrent/jackalope. Unfortunately, the most important code snippet for you was dropped from the repo. I added smartrent/jackalope#28 to see if someone could post it back. I'll check back during the week if no one responds.

@jjcarstens
Copy link
Member

FWIW, first time communication with AWS MQTT typically requires that your signer CA cert be in with the cacerts list as well.

So for your options, you'd need something like:

...
    cacerts: [your_signer_ca_der | :certifi.cacerts()],
    certfile: "/srv/erlang/lib/network_led-0.1.0/priv/testdev01.cert",
    keyfile: "/srv/erlang/lib/network_led-0.1.0/priv/testdev01.private.key",
...

where your_signer_ca_der is the CA certificate used to create testdev01.cert, read in and converted to DER format.

This is typically just needed for initial connect. If that doesn't fix things, there is probably something with the AWS setup that needs to be handled there

@MAkcanca
Copy link
Author

FWIW, first time communication with AWS MQTT typically requires that your signer CA cert be in with the cacerts list as well.

So for your options, you'd need something like:

...
    cacerts: [your_signer_ca_der | :certifi.cacerts()],
    certfile: "/srv/erlang/lib/network_led-0.1.0/priv/testdev01.cert",
    keyfile: "/srv/erlang/lib/network_led-0.1.0/priv/testdev01.private.key",
...

where your_signer_ca_der is the CA certificate used to create testdev01.cert, read in and converted to DER format.

This is typically just needed for initial connect. If that doesn't fix things, there is probably something with the AWS setup that needs to be handled there

I will try this one out and update here. Thank you for the insight!

@jjcarstens
Copy link
Member

singer_cert_path
|> File.read!()
|> X509.Certificate.from_pem!()
|> X509.Certificate.to_der()

This should prob do it for you

@MAkcanca
Copy link
Author

What is the correct way to read in the cert file as der?

singer_cert_path
|> File.read!()
|> X509.Certificate.from_pem!()
|> X509.Certificate.to_der()

This should prob do it for you

@MAkcanca
Copy link
Author

MAkcanca commented Nov 30, 2020

I added in the AmazonRootCA1 since I used their One Click Certificate to generate certs, but it still hangs.

Edit: If I remove the customize_hostname_check line, it hangs, otherwise it fails hostname_check bad_cert,hostname_check_failed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants