Contents

HTTPS communication with the AWS IoT Core

Introduction

During the Internet of Things engagements, we need to adapt our solution to the capabilities offered by existing hardware and/or firmware.

In some cases, our devices might not be able to use “fancy” MQTT clients. Is there a way to connect those devices to the AWS IoT Core?

One of the possible options is to use the HTTPS protocol to publish messages from those devices to AWS.

Limitations of the HTTPS protocol

Before I present how can we send messages to AWS IoT Core using the HTTPS protocol, I want to underline some important limitations of this approach:

  • this method is “Publish only” - devices can send messages using HTTPS to the IoT Core, but they can not receive any messages from IoT Core,
  • clientId is not supported and iot:Connection.Thing.ThingName IoT Policy variable is not available for HTTPS connections - this impacts our IoT Policies and makes them hard to manage. If you need a quick introduction to the IoT Core Policy Variables, I described this topic in my previous post.

HTTPS Publish

Before publishing, we need to obtain the AWS IoT device data endpoint (to know the target of our messages):

1
2
3
4
5
aws iot describe-endpoint --profile train --endpoint-type iot:Data-ATS

# {
#     "endpointAddress": "a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com"
# }

I will use a simple curl command to send a message to AWS IoT Core using the HTTPS protocol and device credentials:

1
2
3
4
5
6
7
8
curl --tlsv1.2 --cacert creds/AmazonRootCa1.pem \
    --cert creds/https-thing.pem \
    --key creds/https-thing.key \
    --request POST \
    --data "{ \"temp\": \"25\" }" \
    "https://a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com:8443/topics/dt/https-thing/telemetry"

# {"message":"OK","traceId":"a090eac9-c836-56cc-8b63-1534f59f5036"}

I will use the MQTT test client to verify that our message was received by the AWS IoT Core:

/posts/iot_core_https/https001.png

At this stage, we can process this message the same way we are processing “typical” MQTT messages.

What if we try to send a message to the Topic that is not allowed for our device?

1
2
3
4
5
6
7
8
curl --tlsv1.2 --cacert creds/AmazonRootCa1.pem \
    --cert creds/https-thing.pem \
    --key creds/https-thing.key \
    --request POST \
    --data "{ \"temp\": \"25\" }" \
    "https://a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com:8443/topics/dt/https-thing/wont-work"

# {"message":null,"traceId":"0d91da33-961c-ae9d-9563-1f997169ad34"}

Instead of "message":"OK" we received "message":null.

HTTPS Subscribe

There is no way to subscribe using the HTTPS protocol - in other words, our devices are not able to receive any data from the AWS IoT Core.

QoS

To define the MQTT QoS (Quality of Service) when sending messages using HTTPS add the ?qos= at the end of the URL. If you are not sure what the QoS is, please check my MQTT cheat sheet.

IMPORTANT: Please remember that AWS IoT Core currently supports only QoS 0 and 1 - docs.

1
2
3
4
5
6
7
8
curl --tlsv1.2 --cacert creds/AmazonRootCa1.pem \
    --cert creds/https-thing.pem \
    --key creds/https-thing.key \
    --request POST \
    --data "{ \"temp\": \"26\" }" \
    "https://a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com:8443/topics/dt/https-thing/telemetry?qos=1"

# {"message":"OK","traceId":"0003aa80-96ec-68a5-3504-8322e77108dd"}

/posts/iot_core_https/https002.png

ClientId is NOT supported

Why that is important? Because typically we use the clientId to write flexible yet restrictive IoT Policies.

The Thing Name is obtained from the client ID in the MQTT Connect message sent when a Thing connects to AWS IoT Core - we read this value from the iot:Connection.Thing.ThingName Thing Policy Variable when we use the MQTT protocol.
If this topic is not clear to you please check my previous post.

Unfortunately, the clientId is not set for messages sent using HTTPS.

To verify this, let’s create the following IoT Rule:

/posts/iot_core_https/https003.png

In the SQL statement, we use the clientid() function, which returns the client ID or N/A if that value was not set.

Let’s publish the following message:

1
2
3
4
5
6
7
8
curl --tlsv1.2 --cacert creds/AmazonRootCa1.pem \
    --cert creds/https-thing.pem \
    --key creds/https-thing.key \
    --request POST \
    --data "{ \"temp\": \"27\" }" \
    "https://a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com:8443/topics/dt/https-thing/telemetry?qos=1"

# {"message":"OK","traceId":"f5279eda-d204-b4bf-c254-f2ad639d206d"}

/posts/iot_core_https/https004.png

To compare, we can make a quick test using the MQTT protocol:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
mosquitto_pub -h a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com \
    -i https_thing \
    --cafile creds/AmazonRootCa1.pem \
    --cert creds/https-thing.pem \
    --key creds/https-thing.key \
    -t dt/https-thing/telemetry \
    -m "{\"temp\": \"28\"}" -d -q 1

# Client https_thing sending CONNECT
# Client https_thing received CONNACK (0)
# Client https_thing sending PUBLISH (d0, q1, r0, m1, 'dt/https-thing/telemetry', ... (14 bytes))
# Client https_thing received PUBACK (Mid: 1, RC:0)
# Client https_thing sending DISCONNECT

/posts/iot_core_https/https005.png

Summary

This concludes my short overview of sending messages to the AWS IoT Core using the HTTPS protocol.

If you decide to use this approach, please design AWS IoT Policies with care. Since the clientId is not supported in communication using HTTPS, you need to hardcode your policies which will make them hard to manage at scale.

Support quality content❤️ Donate💰

Sign up for news: (by subscribing you accept the privacy policy)