Contents

AWS IoT Greengrass - permissions overview

Overview

AWS IoT Greengrass is an open source Internet of Things edge runtime and cloud service. It enables efficient management of a huge fleet of IoT devices (called Greengrass Core Devices) and remote deployment + execution of applications at the edge.

To provide those capabilities, Greengrass needs to be authorized to access other AWS Services.

In this post, I will present the minimal set of privileges required for the Greengrass Core Device to operate.

NOTE: I am aware that this post is a bit rough introduction to the AWS IoT Greengrass service. I will mention a few concepts without a proper explanation (like Deployments and Components), but I do hope it will help you understand how the Greengrass service works. I will cover other Greengrass concepts in my future posts.

Required privileges

The Greengrass Core Device is represented in AWS as an IoT Thing.

Greengrass Core required privileges
Greengrass Core required privileges

Connection to the AWS IoT Core

iot:Connect
iot:Connect

iot:Connect represents the permission to connect to the AWS IoT Core message broker.

I covered the Device <-> AWS MQTT Connectivity topic in my previous post

1
2
3
4
5
6
7
{
  "Effect": "Allow",
    "Action": [
      "iot:Connect"
    ],
    "Resource": "arn:aws:iot:{region}:{account}:client/{gg_thing_name}*"
}

The GG Core Device makes multiple connections to the AWS IoT Core, but the IoT Core message broker doesn’t allow for multiple active connections with the same client ID.

Wildcard (*) added to the end of the Thing name variable allows the GG Core Device to establish multiple connections using the client ID with a suffix.

Subscribe, Receive, and Publish to MQTT Topics

iot:Subscribe, iot:Receive, iot:Publish
iot:Subscribe, iot:Receive, iot:Publish

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "Effect": "Allow",
    "Action": [
        "iot:Subscribe"
    ],
    "Resource": [
        "arn:aws:iot:{region}:{account}:topicfilter/$aws/things/{gg_thing_name}*/jobs/*",
        "arn:aws:iot:{region}:{account}:topicfilter/$aws/things/{gg_thing_name}*/shadow/*"
    ]
},
{
    "Effect": "Allow",
    "Action": [
        "iot:Receive",
        "iot:Publish"
    ],
    "Resource": [
        "arn:aws:iot:{region}:{account}:topic/$aws/things/{gg_thing_name}*/jobs/*",
        "arn:aws:iot:{region}:{account}:topic/$aws/things/{gg_thing_name}*/shadow/*",
        "arn:aws:iot:{region}:{account}:topic/$aws/things/{gg_thing_name}*/greengrassv2/health/json"
    ]
}

Before I describe the usage of the above topics, I want to demonstrate the wildcard functionality.

IMPORTANT: AWS IoT Policy supports *, NOT + and # used by MQTT.

I will use the GGCore as the gg_thing_name and try to connect to the /$aws/things/GGCore/greengrassv2/health/json MQTT Topic using the GGCore as the client ID:

1
2
3
mosquitto_pub -h a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com -p 8883 --key GGCore.key --cert GGCore.pem --cafile AmazonRootCA1.pem -d -t /$aws/things/GGCore/greengrassv2/health/json -l -i GGCore
Client GGCore sending CONNECT
Client GGCore received CONNACK (0) <--- It worked.

Now, let’s try to connect to /$aws/things/GGCore1/greengrassv2/health/json topic using the GGCore as the client ID (please mind that I used the GGCore1 as part of my MQTT topic structure):

1
2
3
mosquitto_pub -h a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com -p 8883 --key GGCore.key --cert GGCore.pem --cafile AmazonRootCA1.pem -d -t /$aws/things/GGCore1/greengrassv2/health/json -l -i GGCore
Client GGCore sending CONNECT
Client GGCore received CONNACK (0) <--- It worked.

It worked because of the wildcard suffix added to the GG Thing Name $aws/things/{gg_thing_name}*/greengrassv2/health/json in the above IoT Policy.

Finally, let’s try to use a different clientId (-i GGCore1) during MQTT connection:

1
2
3
mosquitto_pub -h a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com -p 8883 --key GGCore.key --cert GGCore.pem --cafile AmazonRootCA1.pem -d -t /$aws/things/GGCore/greengrassv2/health/json -l -i GGCore1 
Client GGCore1 sending CONNECT
Client GGCore1 received CONNACK (0) <--- It worked.

It worked because of the wildcard suffix added to the GG Thing Name in the IoT Policy Resource for the iot:Connect action (please check the very first IoT Policy I described).

What if we try to connect using a different prefix (not the GGCore) for the client ID?

1
2
3
4
5
mosquitto_pub -h a1pmmrdn6yc5il-ats.iot.eu-west-1.amazonaws.com -p 8883 --key GGCore.key --cert GGCore.pem --cafile AmazonRootCA1.pem -d -t /$aws/things/GGCore/greengrassv2/health/json -l -i GGTestCore
Client GGTestCore sending CONNECT
Client GGTestCore sending CONNECT
Client GGTestCore sending CONNECT <--- Greengrass Core device is not able to establish the MQTT connection
^C

Greengrass Core is not authorized to connect to the AWS IoT Core using GGTestCore as a clientId.

CloudWatch log-group/AWSIotLogsV2/log-events/:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
    "timestamp": "2022-04-15 21:33:31.580",
    "logLevel": "ERROR",
    "traceId": "feb09cc5-5ee3-d05e-01e6-58dce2ac092f",
    "accountId": "693854281758",
    "status": "Failure",
    "eventType": "Connect",
    "protocol": "MQTT",
    "clientId": "GGTestCore",
    "principalId": "238ea65b10cfcc44b0b916cd238b7e69f10bb0f0459f7b89ad0a78f1b58475d7",
    "sourceIp": "81.183.209.43",
    "sourcePort": 55114,
    "reason": "AUTHORIZATION_FAILURE",
    "details": "Authorization Failure"
}

Restrictive IoT Policies are extremely important, that is why I wanted to present all of the above cases.

Greengrass service uses the IoT Jobs to manage Deployments so Greengrass Core needs the Publish/Subscribe to access the following topic /$aws/things/{gg_thing_name}*/jobs/*

I will not explain Greengrass Deployment nor IoT Jobs in this post, I want to focus on the policies required by the Greengrass Core Device (I will cover those topics in the future).

The $aws/things/{gg_thing_name}*/greengrassv2/health/json topic is used by the Telemetry agent running on the Greengrass Core Device. That agent collects local telemetry data and publishes it to Amazon EventBridge.

If you wonder why Greengrass Core device needs access to the /shadow/ topic ($aws/things/{gg_thing_name}*/shadow/*), you can remove it from the IoT Policy and check the CloudWatch logs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
    "timestamp": "2022-04-15 21:43:31.010",
    "logLevel": "ERROR",
    "traceId": "7d4dc249-f7a4-af51-90b9-3f9b735058f0",
    "accountId": "693854281758",
    "status": "Failure",
    "eventType": "Subscribe",
    "protocol": "MQTT",
    "topicName": "$aws/things/GGCore/shadow/name/AWSManagedGreengrassV2Deployment/update/accepted",
    "clientId": "GGCore",
    "principalId": "ddd6584d835ddf37833785745abe1c5d669f03ebf8a62400fd11746b196cbe50",
    "sourceIp": "81.183.209.43",
    "sourcePort": 63588,
    "reason": "AUTHORIZATION_FAILURE",
    "details": "Authorization Failure"
}

The GG Core device uses the Device Shadow functionality to update the Deployment status.

Greengrass Components

greengrass:ResolveComponentCandidates
greengrass:ResolveComponentCandidates

Greengrass Component is a software that is deployed to and runs on a Greengrass Core Device. In short, Components are applications you push (using Deployments) from AWS Cloud to the Greengrass Device.

Greengrass Device needs the following permissions to obtain the Deployment configuration and receive information about Components:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    {
      "Effect": "Allow",
      "Action": [
        "greengrass:GetComponentVersionArtifact",
        "greengrass:ResolveComponentCandidates",
        "greengrass:GetDeploymentConfiguration"
      ],
      "Resource": [
        "*"
      ]
    }

In this post, I present the minimal policies required by the Greengrass Device. In the “real-file scenario, Greengrass would require additional permissions to access AWS services to provide some actual business value.

I will describe sample use-cases for Greengrass in my future posts. For now, I want to focus on the minimal set of privileges. You should always use the minimal set of privileges sufficient to provide the business value.

Logs

Log Manager Component
Log Manager Component

The Log Manager Component uploads logs from the Greengrass Dore Device (and optionally other applications) to CloudWatch Logs.

This component is not strictly required for Greengrass to operate, but I do recommend sending logs from the edge to the CloudWatch. Monitoring a huge fleet of IoT devices and troubleshooting is way easier when you gather all logs in a single location.

The Log Manager Component requires the following permissions to store logs in the CloudWatch:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogStreams"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

Note: the above json is not an IoT Policy, it is an IAM Policy attached to the IAM Role which Greengrass Core device can assume using the IoT Role alias.

Summary

Once again, sorry for the rough introduction to the AWS IoT Greengrass service. I did my best to explain how this service works. I am aware that this post was not very entertaining to read. Feel free to reach out with suggestions on how I could improve it!

In my future posts, I will present sample business scenarios and how to implement them using the Greengrass service.

Support quality content❤️ Donate💰

Sign up for news: (by subscribing you accept the privacy policy)