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달 전288회 조회
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달 전

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠