ForbiddenException error when using the boto3 publish method with IoTDataPlane

0

I'm attempting to publish to an IoT topic within a lambda using the publish method for the boto3 IoTDataPlane client. However when I invoke the lambda, I get the following exception:

[ERROR] ClientError: An error occurred (ForbiddenException) when calling the Publish operation: None

I have also added an AWS IoT policy to the lambda.

Here's a snippet of the lambda:

import boto3
import json
import logging

logger = logging.getLogger(__name__)
logger.setLevel("DEBUG")

iot_client = boto3.client('iot', region_name='us-east-1')
endpoint_response = iot_client.describe_endpoint(endpointType='iot:Data-ATS')
endpoint_url = f"https://{endpoint_response['endpointAddress']}"
logger.debug(endpoint_url)
client = boto3.client('iot-data', region_name='us-east-1', endpoint_url=endpoint_url)

def handler(event, context):
    topic = "test/topic"
    datum = json.dumps({"a": "b"})
    logger.debug(datum)

    response = client.publish(
        topic=topic,
        qos=0,
        payload=datum,
        retain=True
    )

    logger.debug(response)

And this is the policy statement associated with the lambda:

self._handler.add_to_role_policy(
    iam.PolicyStatement(
        actions=[
            "iot-data:Publish",
            "iot-data:Close",
            "iot-data:AttachPolicy",
            "iot-data:ListNamedShadowsForThing",
            "iot:DescribeEndpoint"
        ],
        resources=[
            "*"
        ],
    )
)
1 Answer
0
Accepted Answer

Hi. I can see why you might assume there is, but there's no iot-data service. You can replace all iot-data references in the policy with just iot. Then you'll be able to publish. BTW, there's no iot:Close action.

Additionally (if the Lambda is in the same account and region as the IoT Core endpoint you want to use), you don't have to explicitly set the endpoint or the region so you could reduce the code down to something like:

import boto3
import json
import logging

logger = logging.getLogger(__name__)
logger.setLevel("DEBUG")

client = boto3.client('iot-data')

def handler(event, context):
    topic = "test/topic"
    datum = json.dumps({"a": "b"})
    logger.debug(datum)

    response = client.publish(
        topic=topic,
        qos=0,
        payload=datum,
        retain=True
    )

    logger.debug(response)

Then you could delete the DescribeEndpoint action from the policy too. And presently, you aren't using the ListNamedShadowsForThing or AttachPolicy actions so these could be deleted too (but you probably know that).

profile pictureAWS
EXPERT
Greg_B
answered 2 years 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