Security best practices in Amazon IoT Core - Amazon IoT Core
Services or capabilities described in Amazon Web Services documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with Amazon Web Services in China (PDF).

Security best practices in Amazon IoT Core

This section contains information about security best practices for Amazon IoT Core. For information about security rules for Industrial IoT solutions, see Ten security golden rules for Industrial IoT solutions.

Protecting MQTT connections in Amazon IoT

Amazon IoT Core is a managed cloud service that makes it possible for connected devices to interact with cloud applications and other devices easily and securely. Amazon IoT Core supports HTTP, WebSocket, and MQTT, a lightweight communication protocol specifically designed to tolerate intermittent connections. If you are connecting to Amazon IoT using MQTT, each of your connections must be associated with an identifier known as a client ID. MQTT client IDs uniquely identify MQTT connections. If a new connection is established using a client ID that is already claimed for another connection, the Amazon IoT message broker drops the old connection to allow the new connection. Client IDs must be unique within each Amazon Web Services account and each Amazon Web Services Region. This means that you don't need to enforce global uniqueness of client IDs outside of your Amazon Web Services account or across Regions within your Amazon Web Services account.

The impact and severity of dropping MQTT connections on your device fleet depends on many factors. These include:

  • Your use case (for example, the data your devices send to Amazon IoT, how much data, and the frequency that the data is sent).

  • Your MQTT client configuration (for example, auto reconnect settings, associated back-off timings, and use of MQTT persistent sessions).

  • Device resource constraints.

  • The root cause of the disconnections, its aggressiveness, and persistence.

To avoid client ID conflicts and their potential negative impacts, make sure that each device or mobile application has an Amazon IoT or IAM policy that restricts which client IDs can be used for MQTT connections to the Amazon IoT message broker. For example, you can use an IAM policy to prevent a device from unintentionally closing another device's connection by using a client ID that is already in use. For more information, see Authorization.

All devices in your fleet must have credentials with privileges that authorize intended actions only, which include (but not limited to) Amazon IoT MQTT actions such as publishing messages or subscribing to topics with specific scope and context. The specific permission policies can vary for your use cases. Identify the permission policies that best meet your business and security requirements.

To simplify creation and management of permission policies, you can use Amazon IoT Core policy variables and IAM policy variables. Policy variables can be placed in a policy and when the policy is evaluated, the variables are replaced by values that come from the device's request. Using policy variables, you can create a single policy for granting permissions to multiple devices. You can identify the relevant policy variables for your use case based on your Amazon IoT account configuration, authentication mechanism, and network protocol used in connecting to Amazon IoT message broker. However, to write the best permission policies, consider the specifics of your use case and your threat model.

For example, if you registered your devices in the Amazon IoT registry, you can use thing policy variables in Amazon IoT policies to grant or deny permissions based on thing properties like thing names, thing types, and thing attribute values. The thing name is obtained from the client ID in the MQTT connect message sent when a thing connects to Amazon IoT. The thing policy variables are replaced when a thing connects to Amazon IoT over MQTT using TLS mutual authentication or MQTT over the WebSocket protocol using authenticated Amazon Cognito identities. You can use the AttachThingPrincipal API to attach certificates and authenticated Amazon Cognito identities to a thing. iot:Connection.Thing.ThingName is a useful thing policy variable to enforce client ID restrictions. The following example Amazon IoT policy requires a registered thing's name to be used as the client ID for MQTT connections to the Amazon IoT message broker:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:Connect", "Resource": [ "arn:aws:iot:us-east-1:123456789012:client/${iot:Connection.Thing.ThingName}" ] } ] }

If you want to identify ongoing client ID conflicts, you can enable and use CloudWatch Logs for Amazon IoT. For every MQTT connection that the Amazon IoT message broker disconnects due to client ID conflicts, a log record similar to the following is generated:

{ "timestamp": "2019-04-28 22:05:30.105", "logLevel": "ERROR", "traceId": "02a04a93-0b3a-b608-a27c-1ae8ebdb032a", "accountId": "123456789012", "status": "Failure", "eventType": "Disconnect", "protocol": "MQTT", "clientId": "clientId01", "principalId": "1670fcf6de55adc1930169142405c4a2493d9eb5487127cd0091ca0193a3d3f6", "sourceIp": "203.0.113.1", "sourcePort": 21335, "reason": "DUPLICATE_CLIENT_ID", "details": "A new connection was established with the same client ID" }

You can use a CloudWatch Logs filter such as {$.reason= "DUPLICATE_CLIENT_ID" } to search for instances of client ID conflicts or to set up CloudWatch metric filters and corresponding CloudWatch alarms for continuous monitoring and reporting.

You can use Amazon IoT Device Defender to identify overly permissive Amazon IoT and IAM policies. Amazon IoT Device Defender also provides an audit check that notifies you if multiple devices in your fleet are connecting to the Amazon IoT message broker using the same client ID.

You can use Amazon IoT Device Advisor to validate that your devices can reliably connect to Amazon IoT Core and follow security best practices.

See also

Keep your device's clock in sync

It's important to have an accurate time on your device. X.509 certificates have an expiry date and time. The clock on your device is used to verify that a server certificate is still valid. If you're building commercial IoT devices, remember that your products may be stored for extended periods before being sold. Real-time clocks can drift during this time and batteries can get discharged, so setting time in the factory is not sufficient.

For most systems, this means that the device's software must include a network time protocol (NTP) client. The device should wait until it synchronizes with an NTP server before it tries to connect to Amazon IoT Core. If this isn't possible, the system should provide a way for a user to set the device's time so that subsequent connections succeed.

After the device synchronizes with an NTP server, it can open a connection with Amazon IoT Core. How much clock skew that is allowed depends on what you're trying to do with the connection.

Validate the server certificate

The first thing a device does to interact with Amazon IoT is to open a secure connection. When you connect your device to Amazon IoT, ensure that you're talking to Amazon IoT and not another server impersonating Amazon IoT. Each of the Amazon IoT servers is provisioned with a certificate issued for the iot.amazonaws.com domain. This certificate was issued to Amazon IoT by a trusted certificate authority that verified our identity and ownership of the domain.

One of the first things Amazon IoT Core does when a device connects is send the device a server certificate. Devices can verify that they were expecting to connect to iot.amazonaws.com and that the server on the end of that connection possesses a certificate from a trusted authority for that domain.

TLS certificates are in X.509 format and include a variety of information such as the organization's name, location, domain name, and a validity period. The validity period is specified as a pair of time values called notBefore and notAfter. Services like Amazon IoT Core use limited validity periods (for example, one year) for their server certificates and begin serving new ones before the old ones expire.

Use a single identity per device

Use a single identity per client. Devices generally use X.509 client certificates. Web and mobile applications use Amazon Cognito Identity. This enables you to apply fine-grained permissions to your devices.

For example, you have an application that consists of a mobile phone device that receives status updates from two different smart home objects – a light bulb and a thermostat. The light bulb sends the status of its battery level, and a thermostat sends messages that report the temperature.

Amazon IoT authenticates devices individually and treats each connection individually. You can apply fine-grained access controls using authorization policies. You can define a policy for the thermostat that allows it to publish to a topic space. You can define a separate policy for the light bulb that allows it to publish to a different topic space. Finally, you can define a policy for the mobile app that only allows it to connect and subscribe to the topics for the thermostat and the light bulb to receive messages from these devices.

Apply the principle of least privilege and scope down the permissions per device as much as possible. All devices or users should have an Amazon IoT policy in Amazon IoT that only allows it to connect with a known client ID, and to publish and subscribe to an identified and fixed set of topics.

Use a second Amazon Web Services Region as backup

Consider storing a copy of your data in a second Amazon Web Services Region as a backup. Note that the Amazon solution named Disaster Recovery for Amazon IoT is no longer available. While the associated GitHub library remains accessible, Amazon deprecated it in July 2023 and no longer provides maintenance or support for it. To implement your own solutions or to explore additional support options, visit Contact Amazon. If there is an Amazon Technical Account Manager associated with your account, reach out to them for help.

Use just in time provisioning

Manually creating and provisioning each device can be time consuming. Amazon IoT provides a way to define a template to provision devices when they first connect to Amazon IoT. For more information, see Just-in-time provisioning.

Permissions to run Amazon IoT Device Advisor tests

The following policy template shows the minimum permissions and IAM entity required to run Amazon IoT Device Advisor test cases. You will need to replace your-device-role-arn with the device role Amazon Resource Name (ARN) that you created under the prerequisites.

{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "iam:PassRole", "Resource": "your-device-role-arn", "Condition": { "StringEquals": { "iam:PassedToService": "iotdeviceadvisor.amazonaws.com" } } }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "execute-api:Invoke*", "iam:ListRoles", // Required to list device roles in the Device Advisor console "iot:Connect", "iot:CreateJob", "iot:DeleteJob", "iot:DescribeCertificate", "iot:DescribeEndpoint", "iot:DescribeJobExecution", "iot:DescribeJob", "iot:DescribeThing", "iot:GetPendingJobExecutions", "iot:GetPolicy", "iot:ListAttachedPolicies", "iot:ListCertificates", "iot:ListPrincipalPolicies", "iot:ListThingPrincipals", "iot:ListThings", "iot:Publish", "iot:StartNextPendingJobExecution", "iot:UpdateJobExecution", "iot:UpdateThingShadow", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:DescribeLogGroups", "logs:DescribeLogStreams", "logs:PutLogEvents", "logs:PutRetentionPolicy" ], "Resource": "*" }, { "Sid": "VisualEditor2", "Effect": "Allow", "Action": "iotdeviceadvisor:*", "Resource": "*" } ] }

Cross-service confused deputy prevention for Device Advisor

The confused deputy problem is a security issue where an entity that doesn't have permission to perform an action can coerce a more-privileged entity to perform the action. In Amazon, cross-service impersonation can result in the confused deputy problem. Cross-service impersonation can occur when one service (the calling service) calls another service (the called service). The calling service can be manipulated to use its permissions to act on another customer's resources in a way it should not otherwise have permission to access. To prevent this, Amazon provides tools that help you protect your data for all services with service principals that have been given access to resources in your account.

We recommend using the aws:SourceArn and aws:SourceAccount global condition context keys in resource policies to limit the permissions that Device Advisor gives another service to the resource. If you use both global condition context keys, the aws:SourceAccount value and the account in the aws:SourceArn value must use the same account ID when used in the same policy statement.

The value of aws:SourceArn must be the ARN of your suite definition resource. The suite definition resource refers to the test suite you created with Device Advisor.

The most effective way to protect against the confused deputy problem is to use the aws:SourceArn global condition context key with the full ARN of the resource. If you don't know the full ARN of the resource or if you are specifying multiple resources, use the aws:SourceArn global context condition key with wildcards (*) for the unknown portions of the ARN. For example, arn:aws:iotdeviceadvisor:*:account-id:suitedefinition/*

The following example shows how you can use the aws:SourceArn and aws:SourceAccount global condition context keys in Device Advisor to prevent the confused deputy problem.

{ "Version": "2012-10-17", "Statement": { "Sid": "ConfusedDeputyPreventionExamplePolicy", "Effect": "Allow", "Principal": { "Service": "iotdeviceadvisor.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "ArnLike": { "aws:SourceArn": "arn:aws:iotdeviceadvisor:us-east-1:123456789012:suitedefinition/ygp6rxa3tzvn" }, "StringEquals": { "aws:SourceAccount": "123456789012" } } } }