Using Thing Policy Variable to set permissions for shadow interactions with greengrass

0

I am trying to set an IoT policy which uses "${iot:Connection.Thing.ThingName} variable to access the thing name for setting these permissions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:DeleteThingShadow",
      "Resource": [
        "arn:aws:iot:region:123456789101:thing/${iot:Connection.Thing.ThingName}",
        "arn:aws:iot:region:123456789101:thing/${iot:Connection.Thing.ThingName}/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:GetThingShadow",
      "Resource": [
        "arn:aws:iot:region:123456789101:thing/${iot:Connection.Thing.ThingName}",
        "arn:aws:iot:region:123456789101:thing/${iot:Connection.Thing.ThingName}/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:UpdateThingShadow",
      "Resource": [
        "arn:aws:iot:region:123456789101:thing/${iot:Connection.Thing.ThingName}",
        "arn:aws:iot:region:123456789101:thing/${iot:Connection.Thing.ThingName}/*"
      ]
    }
]
}

When I restart greengrass I get the following errors when trying to sync

2023-08-25T06:11:59.847Z [INFO] (pool-2-thread-17) com.aws.greengrass.shadowmanager.sync.strategy.BaseSyncStrategy: sync. Executing sync request. {Type=FullShadowSyncRequest, thing name=Dev, shadow name=onwatch_notifications-plugin}
2023-08-25T06:12:00.128Z [ERROR] (pool-2-thread-17) com.aws.greengrass.shadowmanager.sync.model.BaseSyncRequest: Could not execute cloud shadow get request. {thing name=Dev, shadow name=onwatch_notifications-plugin}
2023-08-25T06:12:00.129Z [ERROR] (pool-2-thread-17) com.aws.greengrass.shadowmanager.sync.strategy.BaseSyncStrategy: sync. Skipping sync request. {thing name=Dev, shadow name=onwatch_notifications-plugin}
com.aws.greengrass.shadowmanager.exception.SkipSyncRequestException: software.amazon.awssdk.services.iotdataplane.model.IotDataPlaneException: null (Service: IotDataPlane, Status Code: 403, Request ID: d737e717-18d2-0c19-cf54-70e220ef87d6)
        at com.aws.greengrass.shadowmanager.sync.model.BaseSyncRequest.getCloudShadowDocument(BaseSyncRequest.java:407)
        at com.aws.greengrass.shadowmanager.sync.model.FullShadowSyncRequest.execute(FullShadowSyncRequest.java:79)
        at com.aws.greengrass.shadowmanager.sync.SyncHandler.lambda$static$0(SyncHandler.java:98)
        at com.aws.greengrass.util.RetryUtils.runWithRetry(RetryUtils.java:50)
        at com.aws.greengrass.shadowmanager.sync.SyncHandler.lambda$static$1(SyncHandler.java:96)
        at com.aws.greengrass.shadowmanager.sync.strategy.BaseSyncStrategy.lambda$new$0(BaseSyncStrategy.java:155)
        at com.aws.greengrass.shadowmanager.sync.strategy.BaseSyncStrategy.syncLoop(BaseSyncStrategy.java:366)
        at com.aws.greengrass.shadowmanager.sync.strategy.RealTimeSyncStrategy.syncLoop(RealTimeSyncStrategy.java:77)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: software.amazon.awssdk.services.iotdataplane.model.IotDataPlaneException: null (Service: IotDataPlane, Status Code: 403, Request ID: d737e717-18d2-0c19-cf54-70e220ef87d6)
        at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleErrorResponse(CombinedResponseHandler.java:125)
        at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleResponse(CombinedResponseHandler.java:82)
        at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:60)
        at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:41)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:40)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:30)
        at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:73)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:42)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:78)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:40)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:50)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:36)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:81)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:36)
        at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206)
        at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:56)
        at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:36)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.executeWithTimer(ApiCallTimeoutTrackingStage.java:80)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:60)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:42)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:48)
        at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:31)
     

I can change the policy to include the actual thing name "Dev" and it then syncs successfully

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:DeleteThingShadow",
      "Resource": [
        "arn:aws:iot:region:123456789101:thing/Dev",
        "arn:aws:iot:region:123456789101:thing/Dev/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:GetThingShadow",
      "Resource": [
        "arn:aws:iot:region:123456789101:thing/Dev",
        "arn:aws:iot:region:123456789101:thing/Dev/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:UpdateThingShadow",
      "Resource": [
        "arn:aws:iot:region:123456789101:thing/Dev",
        "arn:aws:iot:region:123456789101:thing/Dev/*"
      ]
    }
]
}

I am using the same variable for iot:Publish which is working fine:

Allow	iot:Publish	arn:aws:iot:region:123456789101:topic/onwatchIot/${iot:Connection.Thing.ThingName}/*
已提问 9 个月前289 查看次数
2 回答
0
已接受的回答

Hi Phil. Unfortunately the thing policy variables are not currently supported for Greengrass core devices: https://docs.aws.amazon.com/greengrass/v2/developerguide/device-auth.html#iot-policies

Enter image description here

UPDATE: The GG data plane operations are listed here: https://docs.aws.amazon.com/greengrass/v2/developerguide/device-auth.html#iot-policies. Basically, the Thing name variable doesn't work for those, because GG data plane operations are HTTP requests, and the thing name variable is derived from the MQTT client ID. As stated here: https://docs.aws.amazon.com/iot/latest/developerguide/thing-policy-variables.html.

This policy variable is only available when a device connects over MQTT or MQTT over the WebSocket protocol.

And shadow manager makes HTTP requests to get/update/delete/ shadows.

Also be careful about the effect of multiple connections as outlined here: https://docs.aws.amazon.com/greengrass/v2/developerguide/device-auth.html#greengrass-core-minimal-iot-policy. That is, the client ID won't match the Thing name on all connections.

profile pictureAWS
专家
Greg_B
已回答 9 个月前
0

Thanks Greg,

I'm not quite sure I understand the where the policy variable (iot:Connection:Thing.*) can and cant be used. Can you clarify what is a Greengrass data plane operation?

I am using the following IoT Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:DeleteThingShadow",
      "Resource": [
        "arn:aws:iot:ap-southeast-2:123456778910:thing/${iot:Connection.Thing.ThingName}",
        "arn:aws:iot:ap-southeast-2:123456778910:thing/${iot:Connection.Thing.ThingName}/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:GetThingShadow",
      "Resource": [
        "arn:aws:iot:ap-southeast-2:123456778910:thing/${iot:Connection.Thing.ThingName}",
        "arn:aws:iot:ap-southeast-2:123456778910:thing/${iot:Connection.Thing.ThingName}/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:UpdateThingShadow",
      "Resource": [
        "arn:aws:iot:ap-southeast-2:123456778910:thing/${iot:Connection.Thing.ThingName}",
        "arn:aws:iot:ap-southeast-2:123456778910:thing/${iot:Connection.Thing.ThingName}/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:ListNamedShadowsForThing",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": "arn:aws:iot:ap-southeast-2:123456778910:topicfilter/onwatchIot/${iot:Connection.Thing.ThingName}*/clientRequests"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Receive",
      "Resource": "arn:aws:iot:ap-southeast-2:123456778910:topic/onwatchIot/${iot:Connection.Thing.ThingName}*/clientRequests"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": "arn:aws:iot:ap-southeast-2:123456778910:topic/onwatchIot/${iot:Connection.Thing.Attributes[fleetOperator]}/${iot:Connection.Thing.ThingName}/*"
    },
    {
      "Effect": "Allow",
      "Action": "iot:AssumeRoleWithCertificate",
      "Resource": "arn:aws:iot:ap-southeast-2:123456778910:rolealias/TokenExchangeRoleAlias"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": "arn:aws:iot:ap-southeast-2:123456778910:topic/onwatchIot/${iot:Connection.Thing.ThingName}/*"
    }
  ]
}

I use the greengrass IPC client to subscribe to and receive on topic onwatchIot/Dev-plugin/clientRequests it works successfully, and I am using the policy variable. Not sure what the difference is?

已回答 9 个月前

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

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

回答问题的准则

相关内容