How do I publish a message to an IoT thing topic on AWS using HTTPS and Postman?
Asked Answered
L

1

5

I would like to publish a message to an IoT thing topic on AWS using HTTPS and Postman.

EDIT: I have edited majority of the post to include a step-by-step process of the thing i created

I created a thing called TestDevice by following these steps:

AWS IoT console > Manage (left dashboard panel) > All devices > Things > Create Things (on the ceneter page) > Create Single Thing > Named it TestDevice (No shadow and additional configurations) > Auto generate a new certificate > created a policy named TestDevice-policy (this will open a new browser tab where you will create the policy > attach it to the thing > Finish creating the thing and download all the certificates

The policy looks like this:

enter image description here

The certificates downloaded looks like this :

enter image description here

Now according to the AWS developer guide, my endpoint should be:

https://xxx-ats.iot.ap-northeast-1.amazonaws.com/topics/TestTopic?qos=1

I opened the AWS IoT MQTT test client in the console and subscribed to # which should allow me to see all incoming messages.

Setting up postman as @Ermiya Eskandary Instructed

enter image description here

I get a socket hang-up error on POSTMAN when hitting send:

enter image description here

So i can gurantee that it is not an AWS IoT setting problem because running the python examples in the AWS developer guide i get an "OK" response

enter image description here enter image description here

So i must have done some postman settings wrong

Leeway answered 5/12, 2023 at 16:2 Comment(2)
You are trying to use a HTTPs protocol to publish in a MQTT protocol. The fact that both uses CA certificates does not mean that they are interchangeable. They are not. You will always need some middle application between them using a library to connect to the MQTT. There is a new feature that allow POSTMAN to connect directly to a MQTT broker, but it is not a HTTPs. -> blog.postman.com/postman-supports-mqtt-apisPhoneme
@Phoneme I am not trying to connect to a MQTT protocol via HTTPs, I am trying to connect to AWS IoT which ACCEPTS HTTPS. Here is their developer guide in how to publish using HTTPS, It even has examples on how to do it (PYTHON and CURL). The middle application is already baked in AWS Iot. Making it work postman is the tricky bit.Leeway
R
9

Postman can definitely connect to the HTTPs endpoint and publish a message, though the AWS IoT docs admittedly aren't the best on explaining this.

I want to make sure I answer all of your questions so there's a lot of detail here, but we'll go through it bit by bit.


Now i opened the AWS Iot test console and subscribe to a #

Correct.

# and + are the MQTT wildcard characters. Subscribing to either of them will subscribe you to all topics.

It's easy to confuse them with the AWS IAM policy wildcard characters - * & ? - which you can use in IoT Core policies but not for subscriptions. Using them as topic names for subscriptions won't yield any messages.


Which certificates do I use?

Your downloaded connection kit for Windows (as the names will differ for Linux/Mac) will have at a minimum:

  • {thing-name}.cert.pem: device certificate
  • {thing-name}.private.key: public key file
  • {thing-name}.public.key: private key file

I'm using the eu-west-1 region which uses the above naming convention however, clearly it's not consistent across all regions.

Nonetheless, you can deduce it most of the time as the device certificate is the .pem file, the private key has private in the name & the public key has public in the name.

In your case, they are respectively:

  • certificate.cert.pem: device's certificate
  • public.pem.key: device's public key file
  • private.pem.key: device's private key file

You then may also have 1 or more CA (certificate authority) certificate files. Currently, per docs, AWS IoT Core server authentication certificates are signed by one of the following root CA certificates (but you might also see CA 2 and 4 :

  • RSA 2048 bit key: Amazon Root CA 1
  • ECC 256 bit key: Amazon Root CA 3

In your case, you have both Root CA 1 & Root CA 3 with names that conveniently point out the cipher suite:

Cipher suites are outside of the scope of this answer but we'll stick to RSA 2048.


So, what do we need for Postman?

We need:

  • 1 certificate authority: RSA2048AmazonRootCA1.pem
  • device's certificate: certificate.cert.pem
  • device's private key: private.pem.key

This is how they map in Postman.

Settings > Certificates > CA Certificates

  1. Toggle to ON
  2. Select your root CA (any would work with Postman, but other tools may not always support ECC)

enter image description here

  1. Add Certificate

enter image description here

  1. We have a few values here:
  • Host:
  1. https://, set by Postman
  2. your AWS IoT Data-ATS endpoint (aws iot describe-endpoint --endpoint-type iot:Data-ATS), set by you e.g. xxx-ats.iot.eu-west-1.amazonaws.com
  3. 8443, set by you, as the port - do not use 443
  • CRT file: select your device's certificate.

Postman is using the .crt filename convention but that's all it is - a filename convention. The format of .crt files are either in DER or PEM. AWS has used .pem here to signal the PEM format i.e. Base64 encoding of the certificate.

Postman fully supports .pem but doesn't currently support DER, so we can just keep this .pem file as it is.

Side note: feel free to add .crt on to the end to have Windows recognise it as a certificate file & allow you to double click on it to check details.

  • KEY file: select your device's private key

  • PFX file: leave as-is

  • Passphrase: leave as-is

enter image description here

  1. Click Add - this should be your final configuration

enter image description here


Postman is now correctly configured to send requests to the HTTPS endpoint.

The reason IoT throws Missing authentication when trying to publish messages via the HTTPS endpoint is that port 443 requires a custom ALPN protocol name of x-amzn-http-ca. You can only communicate over port 443 without a custom ALPN protocol name set, if you use AWS Sig V4 for authentication.

In this case, as we're using X.509 client certificate authentication, port 8443 allows us to not need to configure ALPN. ALPN is impossible to configure within Postman & difficult to configure for curl, so we should opt for either

  • Port 443, AWS Signature v4 authentication
  • Port 8443, X.509 certificate authentication

I've opted for certificate authentication.

This is highlighted in the AWS docs, with my emphasis on the bold items:

Protocol Operations Supported Authentication Port ALPN Protocol Name
MQTT over WebSocket Publish, Subscribe Signature Version 4 443 N/A
MQTT over WebSocket Publish, Subscribe Custom authentication 443 N/A
MQTT Publish, Subscribe X.509 client certificate 443 x-amzn-mqtt-ca
MQTT Publish, Subscribe X.509 client certificate 8883 N/A
MQTT Publish, Subscribe Custom authentication 443 mqtt
HTTPS Publish only Signature Version 4 443 N/A
HTTPS Publish only X.509 client certificate 443 x-amzn-http-ca
HTTPS Publish only X.509 client certificate 8443 N/A
HTTPS Publish only Custom authentication 443 N/A

Final thing to check is that the policies attached to your certificate allow you to publish to the topic you want to publish to, using that certificate.

At the very least, you need to have the below policy attached with the iot:Publish policy action:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": "arn:aws:iot:eu-west-1:xxx:topic/my-topic"
    }
  ]
}

Replace eu-west-1 with your region, xxx with your AWS account ID & my-topic with your topic name.

If you want to be able to publish to any topic, use the * wildcard in the ARN as detailed before (and not #!) e.g.

arn:aws:iot:eu-west-1:xxx:topic/*

Once you have the correct CA, the correct device certificate set up with the host set to the ATS signed data endpoint, the port set to 8443, the KEY file set to your private key and your certifcate has the right policy attached in the console, you're ready to send your request.

  • Method: POST
  • URL: https://xxx:8443/topics/yyy?qos=1, replacing xxx with your ATS endpoint and yyy with your topic name
  • Body: raw - Text/JSON as content type, doesn't really matter
  • Headers: very important to keep Content-Length otherwise you will get Message cannot be displayed in specified format. in the AWS MQTT test client

enter image description here


Hit send & a 200 OK response signals success:

{
    "message": "OK",
    "traceId": "xxx-xxx-xxx-xxx-xxx"
}

If you haven't set up your policies correctly to allow publishing to the topic, you'll instead get a 403 Forbidden response that signals failure.

Note message is set to null:

{
    "message": null,
    "traceId": "xxx-xxx-xxx-xxx-xxx"
}

If it's successful, check the console & your message will be there:

enter image description here


P.S. the developer guide does indeed have a typo with the rogue ". I've submited feedback to hopefully rectify this :)

Recycle answered 12/12, 2023 at 2:13 Comment(7)
That seems more detailed than my answer. Upvoted.Bloodstock
Thank you very much for this, So i think in my previous attempt 2 things were not setup correctly, AWS IoT policies and my postman settings, I have deleted my thing and recreated them using the steps on my edited original post. So after creating the thing i have tested it using the python example in the developer guide, and i got an okay message , it even shows up in the MQTT Test console. I am confident that i have done the AWS IoT settings correctly this time.Leeway
As for POSTMAN however, i am having a socket hang up error when i followed your steps. Can you please check if i did everything correctly (i edited the orignal post with how i did my postman settings.Leeway
@Jakequin Sometimes, Postman can be a bit buggy with the certificates. Restart the application and remove + add again. Make sure you’re using the latest version of Postman. If none of that works, click view in console and copy paste the full output to the question but my steps definitely work 100%.Recycle
@ErmiyaEskandary your right, postman a bit buggy with https i guess, reinstalled postman and i got "ok" response. Thank you so much sir, this has been a great help !Leeway
I would like to vent that the docs does not really make it clear, It would be a great help for first timers using AWS IoT if they could have atleast mention to check if the necessary policies are there. Also would you happen to know why MQTT test console throw a warning "Message cannot be displayed in specified format" ? Im pretty sure i sent a proper JSON string.Leeway
@Jakequin Glad it worked! 🎉 I agree with you on the documentation. RE 'Message cannot...', it can happen if you don't send the Content-Length header with your request. Also definitely ensure it's valid JSON. If still having issues, feel free to create a new question and I'm happy to take a look.Recycle

© 2022 - 2024 — McMap. All rights reserved.