
AWS IoT Core is an amazing (and often overlooked) service as I said before whencomparing IoT Core to API Gateway Websockets. To summarize, IoT Core manages it own connections, it has a powerful system of topics and rules, it scales well and, not unimportant, it's quite cheap.
However, IoT Core can also be intimidating anddifficult to start with because ofthings,fleets,shadow devices andcertificates. The good news is that those things are not at all mandatory to use this service. While maybe not obvious at first sight, there are ways to just connect some clients to IoT Core without first registering or managing them.
I will be posting a few articles to cover basic usage of IoT Core aimed at developers who are looking for an easy and flexible way of bi-directional communication between clients and server using websockets.
Part 1: Introduction & Permissions (this one!)
Part 2: Connect using a presigned url
Part 3: Connect using a custom authorizer
Part 4: Topic Rules
What is IoT Core?
Simply put,and maybe not giving enough credit, IoT Core is an MQTT broker. MQTT is a lightweight publish-subscribe protocol. The MQTT broker acts as the central hub between connected clients that can send and reach messages to each other. Messages are sent over topics. A topic is a hierarchical string separated by slashes, for instancesensor/temperature/room1. A client can send temperature updates to this topic every minute and another client might be subscribed to this topic and receives all temperatures that are sent to do something with it.
MQTT has many advanced options and use cases that I won't cover here. If you want to know more about them I recommend reading morehere. For the rest of this series, it's enough to know that there is a central broker (IoT Core) and clients (ie: a web browser) that can publish and receive messages.
Topic Wildcards
In atopic, a+ character can be used as a wildcard for one level while a# character can be used for a multi level wildcard. It is possible to have more than 1 single level wildcard, likesensor/+/+ however it's not possible to have more than 1 multi level wildcard (which makes sense).
Looking at the previous example, if a client is interested in temperatures of all rooms, it can subscribe tosensor/temperature/# where the # character is a wildcard in MQTT. This means that if a client wants the informations ofall sensors, it can listen tosensor/#. It is also possible to subscribe tosensor/+/room1 to receive all messages (temperature and others) of room1.
Security
For simple use of IoT Core, there are 4 permissions that you need to know about.Applying least-privilege permissions obviously also applies to IoT Core. In case a client performs an action that is not allowed by it's policy, the client will be disconnected by the server.
It's important to realize thatMQTT wildcards are treated as literal characters in IAM permissions. This means that you can use the?,*,+ and# in the IAM policy but the? and* will be treated only as wildcard for the IAM policy itself while+ and# are treated as wildcards for topics in IoT Core. I will explain this using several examples.
Permissions
iot:Connect
First, your client needs to be able to connect to the server. The client ID must beunique per region, otherwise the previously connected client with the same client ID will be disconnected.
Examplesarn:aws:iot:{region}:{account-id}:client/*
Allows to connect usingany client ID.
arn:aws:iot:{region}:{account-id}:client/sensor-123
Allows to connect assensor-123.
arn:aws:iot:{region}:{account-id}:client/sensor-???
Allows to connect using any client ID as long as it starts withsensor- and ends with 3 characters. This means thatsensor-123,sensor-foo will work, butsensor,sensor-foobar andsensor-123456 won't work.
arn:aws:iot:{region}:{account-id}:client/sensor-*
Allows to connect using any client ID as long as it starts withsensor-.
arn:aws:iot:{region}:{account-id}:client/user-????????-????-????-????-????????????
Allows to connect usinguser-{uuid}.
iot:Subscribe
Before a client can receive messages, the client must first subscribe to one or multiple topics.
Examplesarn:aws:iot:{region}:{account-id}:topicfilter/updates
Allows to subscribe toupdates.
arn:aws:iot:{region}:{account-id}:topicfilter/updates/sensor-???
Allows to subscribe toupdates/sensor-123,updates/sensor-foo and other variants as long as the topic starts withupdates/ and then has a second level starting withsensor- and then 3 characters. It won't accept updates/foo-123 or "updates/sensor-123/foo".
arn:aws:iot:{region}:{account-id}:topicfilter/updates/sensor-*
Allows to subscribe toupdates/sensor-123,updates/sensor-123/foo, and/or "updates/sensor-123/foo/bar/baz" because the * allows for any level of depth in the topic.
arn:aws:iot:{region}:{account-id}:topicfilter/updates/sensor-*/???
Allows to subscribe toupdates/sensor-123/foo,updates/sensor-12345678/bar and other variants as long as the topic starts with "updates/sensor-" and has a second level with exactly 3 characters. It won't acceptupdates/sensor-1 orupdates/sensor-12345/#.
You can of course use the wildcards in MQTT too if you want.
arn:aws:iot:{region}:{account-id}:topicfilter/updates/+
Allows to subscribe totopic/updates/+ only as the+ is treated as a literal in the policy.
arn:aws:iot:{region}:{account-id}:topicfilter/updates/#
Allows to subscribe totopic/updates/# only as the# is treated as a literal in the policy.
iot:Receive & iot:Publish
iot:Receive allows the client to receive messages over the topics that it is subscribed to while iot:Publish allows the client to publish messages that can be received by other clients and/or topic rules.
The iot:Receive & iot:Publish permissions have the same structure as iot:Subscribe with the only difference that it uses "topic" instead of "topicfilter". Usually the iot:Subscribe and iot:Receive will be the same as it doesn't make sense to allow receiving on topics the client isn't allowed to subscribe on and vice versa.
Examplesarn:aws:iot:{region}:{account-id}:topic/updates
arn:aws:iot:{region}:{account-id}:topic/updates/sensor-???
arn:aws:iot:{region}:{account-id}:topic/updates/sensor-*
arn:aws:iot:{region}:{account-id}:topic/updates/sensor-*/???
arn:aws:iot:{region}:{account-id}:topic/updates/+
arn:aws:iot:{region}:{account-id}:topic/updates/#
Creating a policy
Since the permissions and values have different formats, you can easily combine everything in a single policy:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:Connect", "iot:Subscribe", "iot:Receive" ], "Resource": [ "arn:aws:iot:{region}:{account-id}:client/sensor-*", "arn:aws:iot:{region}:{account-id}:topicfilter/sensor-*/???", "arn:aws:iot:{region}:{account-id}:topic/sensor-*/???" ] } ]}
In the next article I will explain how to connect to IoT Core using a presigned url.
Top comments(1)

- LocationVancouver, Canada
- Joined
I second, I have done crazy things with IoT core and able to create POCs with realtime communication in minutes. I guess many other services also offer that capability but I really like the simplicity of IoT core, once you really understand the content of this post 😅
For further actions, you may consider blocking this person and/orreporting abuse