IoT policy to restrict MQTT publish/subscribe by Thing Name

0

Good morning. I want to apply a MQTT policy that grants the IoT thing access to certain topic. For example, assuming that the thing name is 0R281, I would like a policy that allows the thing to publish only in a topic with the following name xgate/0R281/data

I created a policy structured like this

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": "iot:Connect",
			"Resource": "arn:aws:iot:eu-west-1:<acc>:client/${iot:Connection.Thing.ThingName}"
		},
		{
			"Effect": "Allow",
			"Action": "iot:Subscribe",
			"Resource": "arn:aws:iot:eu-west-1:<acc>:topicfilter/xgate/${iot:Connection.Thing.ThingName}/data"
		},
		{
			"Effect": "Allow",
			"Action": "iot:Publish",
			"Resource": "arn:aws:iot:eu-west-1:<acc>:topic/xgate/${iot:Connection.Thing.ThingName}/data"
		}
	]
}

but it does not work. Trying with a policy made like this obviously works,

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:", "Resource": "" } ] }

I don't understand where the mistake is

3 Answers
0
Accepted Answer

Hi. What MQTT client ID is your device using? For the iot:Connection.Thing.ThingName policy variable to work, the client ID must match the Thing name. And does your device use the same certificate as what's attached to the Thing in the registry?

https://docs.aws.amazon.com/iot/latest/developerguide/thing-policy-variables.html

The thing name is obtained from the client ID in the MQTT Connect message sent when a thing connects to AWS IoT Core.

AWS IoT Core uses the certificate the device presents when it authenticates to determine which thing to use to verify the connection.

UPDATE: The problem is that the client ID you're using in the Python code should just be 0R281 not arn:aws:iot:eu-west-1:<acc>:client/0R281. I also recommend you swap to the V2 SDK (https://github.com/aws/aws-iot-device-sdk-python-v2), although that's not an immediate concern.

profile pictureAWS
EXPERT
Greg_B
answered 4 months ago
profile picture
EXPERT
reviewed a month ago
  • Answer updated now that I've seen your code. As suspected, the client ID doesn't match the Thing name.

0

I created the thing and then created and downloaded the certificates Enter image description here I associated the certificate with the policy written before ​Enter image description here Using the Python SDK I instantiated an MQTT client for sending messages with the certificates mentioned above Enter image description here

The client that I instantiate uses the following class defined as follows ​

from AWSIoTPythonSDK import MQTTLib as AWSIoTPyMQTT
class AwsClient:
    def __init__(
        self,
        ca_file_path: str,
        key_path: str,
        certificate_path: str,
        client_id: str,
        endpoint: str,
        port: int = 8883,
    ):
        self.ca_file_path = ca_file_path
        self.key_path = key_path
        self.certificate_path = certificate_path
        self.client_id = client_id
        self.port = port
        self.endpoint = endpoint

    def get_client(self):
        aws_client = AWSIoTPyMQTT.AWSIoTMQTTClient(self.client_id)
        aws_client.configureEndpoint(self.endpoint, self.port)
        aws_client.configureCredentials(
            CAFilePath=self.ca_file_path,
            KeyPath=self.key_path,
            CertificatePath=self.certificate_path,
        )
        return aws_client

when the policy has the first definition that I specified in the first post as its active version, the message is not sent and I get the following error

​AWSIoTPythonSDK.exception.AWSIoTExceptions.connectTimeoutException

If instead I use the second policy mentioned as the active version of the policy (the less restrictive one) the message is sent and I see it received as in the following image

Enter image description here

answered 4 months ago
  • Hi. The problem is that the client ID you're using in the Python code should just be 0R281 not arn:aws:iot:eu-west-1:<acc>:client/0R281. I also recommend you swap to the V2 SDK (https://github.com/aws/aws-iot-device-sdk-python-v2), although that's not an immediate concern.

0

specifying the client with only OR 281 in the code works, thank you very much

answered 4 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions