aws-greengrass / aws-greengrass-nucleus

The Greengrass nucleus component provides functionality for device side orchestration of deployments and lifecycle management for execution of Greengrass components and applications. This includes features such as starting, stopping, and monitoring execution of components and apps, interprocess communication server for communication between components, component installation and configuration management.
Apache License 2.0
109 stars 45 forks source link

mqttproxy: despite providing component with access controls, publishing to IoT Core fails #1640

Closed Dizzzmas closed 3 months ago

Dizzzmas commented 3 months ago

Describe the bug Despite having wildcard access controls in the component recipe.yaml:

ComponentConfiguration:
  DefaultConfiguration:
    accessControl:
      aws.greengrass.ipc.mqttproxy:
        com.setmixer.heartbeat:mqttproxy:1:
          policyDescription: Allows access to publish to the heartbeat topic.
          operations:
            - "*"
          resources:
            - "*"

Trying to publish a message to IoT Core MQTT topic via greengrass v2 IPC:

from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2
ipc_client = GreengrassCoreIPCClientV2()
ipc_client.publish_to_iot_core(
        topic_name="setmixer/recorders/My_Thing/heartbeat",
        qos=QOS.AT_LEAST_ONCE,
        payload=json.dumps(heartbeat_message).encode('utf-8')
)

Fails with the following error:

2024-07-13T21:49:24.700Z [INFO] (Thread-9) software.amazon.awssdk.eventstreamrpc.RpcServer: New connection code [AWS_ERROR_SUCCESS] for [Id 292, Class ServerConnection, Refs 1](2024-07-13T21:49:24.700633Z) - <null>. {}
2024-07-13T21:49:24.701Z [INFO] (Thread-9) software.amazon.awssdk.eventstreamrpc.ServiceOperationMappingContinuationHandler: aws.greengrass#GreengrassCoreIPC authenticated identity: com.setmixer.heartbeat. {}
2024-07-13T21:49:24.701Z [INFO] (Thread-9) software.amazon.awssdk.eventstreamrpc.ServiceOperationMappingContinuationHandler: Connection accepted for com.setmixer.heartbeat. {}
2024-07-13T21:49:24.701Z [INFO] (Thread-9) software.amazon.awssdk.eventstreamrpc.ServiceOperationMappingContinuationHandler: Sending connect response for com.setmixer.heartbeat. {}
2024-07-13T21:49:24.704Z [INFO] (Thread-9) com.aws.greengrass.builtin.services.mqttproxy.MqttProxyIPCAgent: Not Authorized. {error=Principal com.setmixer.heartbeat is not authorized to perform aws.greengrass.ipc.mqttproxy:aws.greengrass#PublishToIoTCore on resource setmixer/recorders/My_Thing/heartbeat}

To Reproduce Not doing anything special. Just following the doc https://docs.aws.amazon.com/greengrass/v2/developerguide/ipc-iot-core-mqtt.html with a Python component that published a message to iot core topic every minute.

Expected behavior Publishing to IoT Core topic succeeds because correct permissions have been provided according to the docs: https://docs.aws.amazon.com/greengrass/v2/developerguide/ipc-iot-core-mqtt.html

Actual behavior Publishing to IoT Core topic fails with Not Authorized error despite the correct permissions being provided.

Environment

Additional context Publishing to IoT core succeeded once when I tried to isolate a single thing in a group and perform deployment on that group. However, I wasn't able to tell in the end why it succeeded and trying it with other things didn't work.

Also I've verified that my greengrass token exchange role has correct permissions:

  const ggTokenExchangeRole = new CfnRole(stack, "GGTokenExchangeRole", {
    roleName: ggTokenExchangeRoleName!,
    assumeRolePolicyDocument: {
      Version: "2012-10-17",
      Statement: [
        {
          Effect: "Allow",
          Principal: {
            Service: ["credentials.iot.amazonaws.com"],
          },
          Action: ["sts:AssumeRole"],
        },
      ],
    },
    path: "/",
    policies: [
      {
        policyName: `${ggTokenExchangeRoleName!}Access`,
        policyDocument: {
          Version: "2012-10-17",
          Statement: [
            {
              Effect: "Allow",
              Action: [
                "iot:DescribeCertificate",
                "iot:Publish",
                "iot:Subscribe",
                "iot:Connect",
                "iot:Receive",
                "iot:GetThingShadow",
                "iot:UpdateThingShadow",
                "iot:DeleteThingShadow",
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:DescribeLogStreams",
                "s3:GetBucketLocation",
                "cloudwatch:PutMetricData",
              ],
              Resource: "*",
            },
            {
              Effect: "Allow",
              Action: [
                "s3:GetObject",
                "s3:ListBucket",
                "s3:GetObjectAttributes",
              ],
              Resource: `arn:aws:s3:::${greengrassComponentBucket.bucketName}/*`,
            },
          ],
        },
      },
    ],
  });
MikeDombo commented 3 months ago

Hello, Please make sure you are deploying your component with reset to update the default configurations.

https://docs.aws.amazon.com/greengrass/v2/developerguide/troubleshooting.html#update-component-configuration-to-default-configuration

Dizzzmas commented 3 months ago

Thanks, this resolved it! Will be more thorough with consulting the docs in the future.