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 回答
0
已接受的回答

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
专家
Greg_B
已回答 2 年前

您未登录。 登录 发布回答。

一个好的回答可以清楚地解答问题和提供建设性反馈,并能促进提问者的职业发展。

回答问题的准则