This sample demonstrates use of the AWS IoT APIs to securely publish to and subscribe from an MQTT topic. It uses Cognito authentication in conjunction with AWS IoT to create an identity (client certificate and private key) and store it in the iOS keychain. This identity is then used to authenticate to AWS IoT. Once a connection to the AWS IoT platform has been established, the application can operate in either the publish or subscribe role; the data format is a single floating point number in the range of 1-50. A configuration tab is provided allowing the user to select the name of the MQTT topic being published to or subscribed from, or to delete the identity. This application also supports the use of a pre-existing identity.
- Xcode 9.2 and later
- iOS 9 and later
-
The AWS Mobile SDK for iOS is available through CocoaPods. If you have not installed CocoaPods, install CocoaPods:
sudo gem install cocoapods pod setup
-
To install the AWS Mobile SDK for iOS, change the current directory to the one with your Podfile in it and run the following command:
pod install
-
This sample requires Cognito to authorize to AWS IoT in order to create a device certificate. Use Amazon Cognito to create a new identity pool:
-
In the Amazon Cognito Console, press the
Manage Federated Identities
button and on the resulting page press theCreate new identity pool
button. -
Give your identity pool a name and ensure that
Enable access to unauthenticated identities
under theUnauthenticated identities
section is checked. This allows the sample application to assume the unauthenticated role associated with this identity pool. Press theCreate Pool
button to create your identity pool.Important: see note below on unauthenticated user access.
-
As part of creating the identity pool, Cognito will setup two roles in Identity and Access Management (IAM). These will be named something similar to:
Cognito_PoolNameAuth_Role
andCognito_PoolNameUnauth_Role
. You can view them by pressing theView Details
button. Now press theAllow
button to create the roles. -
Save the
Identity pool ID
value that shows up in red in the "Getting started with Amazon Cognito" page, it should look similar to: `us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" and note the region that is being used. These will be used in the application code later. -
Now we will attach a policy to the unauthenticated role which has permissions to access the required AWS IoT APIs. This is done by first creating an IAM Policy in the IAM Console and then attaching it to the unauthenticated role. Click into Roles and search using the name used for the roles created above. Click on the link for the unauth role. Click on the "Add inline policy" button and add the following example policy which can be used with the sample application. This policy allows the application to create a new certificate (including private key) as well as attach an existing policy to a certificate.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:AttachPrincipalPolicy", "iot:CreateKeysAndCertificate", "iot:CreateCertificateFromCsr" ], "Resource": [ "*" ] } ] }
More information on AWS IAM roles and policies can be found here. More information on AWS IoT policies can be found here.
Note: to keep this example simple it makes use of unauthenticated users in the identity pool. This can be used for getting started and prototypes but unauthenticated users should typically only be given read-only permissions if used in production applications. More information on Cognito identity pools including the Cognito developer guide can be found here.
-
-
Note that the application does not actually create the AWS IoT policy itself, rather it relies on a policy to already be created in AWS IoT and then makes a call to attach that policy to the newly created certificate. To create a policy in AWS IoT,
-
Navigate to the AWS IoT Console and press the
Get Started
button. On the resulting page click onSecure
on the side panel and the click onPolicies
. -
Click on
Create a Policy
-
Give the policy a name. Note this name as this is the string you will use in the application when making the attach policy API call.
-
The policy should be created to allow connecting to AWS IoT as well as allowing publishing, subscribing and receiving messages on whatever topics you will use in the sample application. Below is an example policy. This policy allows access to all topics under your AWS IoT account. To scope this policy down to specific topics specify them explicitly as ARNs in the resource section:
"Resource": "arn:aws:iot:<REGION>:<ACCOUNT ID>:topic/mytopic/mysubtopic"
. Note that the firsttopic
is an ARN specifer so this example actually specifies the topicmytopic/mysubtopic
. -
To add this policy, click on
Advanced Mode
and replace the default policy with the following text and then click theCreate
button.{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:Connect", "Resource": "*" }, { "Effect": "Allow", "Action": [ "iot:Publish", "iot:Subscribe", "iot:Receive" ], "Resource": "*" } ] }
-
-
Open
IoTSampleSwift.xcworkspace
. -
Open
awsconfiguration.json
and update the Cognito Identity Pool ID (from the value you saved above) and Cognito region for Cognito Identity Pool ID (for example us-east-1)."CredentialsProvider": { "CognitoIdentity": { "Default": { "PoolId": "CHANGE_ME", "Region": "CHANGE_ME" } } }
-
Open
Constants.swift
and update the following lines with the appropriate constants:let CertificateSigningRequestCommonName = "IoTSampleSwift Application" let CertificateSigningRequestCountryName = "Your Country" let CertificateSigningRequestOrganizationName = "Your Organization" let CertificateSigningRequestOrganizationalUnitName = "Your Organizational Unit" let PolicyName = "YourPolicyName" let AwsRegion = AWSRegionType.Unknown let IOT_ENDPOINT = "https://xxxxxxxxxx.iot.<region>.amazonaws.com" // make sure to include "https://" prefix
Note: The endpoint can be found under IoT Home. Once there, scroll down and click Settings on the side navigation on the left side. For Certificate details, navigate to Secure > Certificates and select the specific certificate to view certificate details such as CommonName (CN), OrganizationName (O), OrganizationUnit(OU), and Country (C).
-
Add the IoT certificate (IoT identity) to the Xcode project
- Follow the instructions below to create the certificate
- Place the PKCS #12 archive (.p12) in the same directory as Info.plist
- Add it to the same group in Xcode as Info.plist
- Select the build targets which will use this IoT identity
-
Build and run the sample app on two different simulators or devices. After you connect then changes in one devices publish panel will show up in the other devices subscribe panel.
The sample application will allow you to connect to the AWS IoT platform, and then publish or subscribe to a topic using MQTT. You can configure the topic name under the 'Configuration' tab; it's set to 'slider' by default (only when you are disconnected). You can use another instance of this application so that one instance publishes while the other subscribes, or you can use the MQTT client in the Amazon AWS IoT console to interact with your application.
You can also configure the sample application to use an existing AWS IoT identity. To do this, create a certificate and private key in the Amazon AWS IoT console and associate it with a policy which allows access to 'iot:*'. Go to the section named Secure and click on Certificates on the side navigation on the left sideN. Download the generated files and use the following command to create a PKCS #12 archive from the certificate and private key (NOTE: the filename must use the .p12 suffix):
openssl pkcs12 -export -in certificate.pem.crt -inkey private.pem.key -out awsiot-identity.p12
When prompted for Enter Export Password:
, enter the default empty string as the export password.
The app will use this IoT identity instead of creating one dynamically. Note that when using your own certificate and private key, the "Delete" option under the "Configuration" tab only deletes them from the keychain; they remain in the application itself and will be re-added into the keychain the next time you connect.