Code Monkey home page Code Monkey logo

thingstack's Introduction

ThingStack

About

This project deploys the necessary AWS IoT components for the provisioning of a Thing (Arduino, in my case) through AWS CloudFormation and the AWS CDK (Python). The project automatically generates a device certificate and uses AWS Secrets Manager for storing for the device's private key. It can be reused to deploy and manage the lifecycle of multiple devices.

The inspiration for this project was twofold:

Prerequisites

Install AWS CLI, AWS CDK, and jq. For example, on macOS with brew:

$ brew install awscli npm jq
$ npm install -g aws-cdk

I have tested this on:

  • macOS Mojave (10.14.5) and Catalina (10.15.4)
  • Python 3.7.2 and 3.8.2
  • AWS CDK 0.36, 1.0, and 1.37.0

Setup

First, configure your AWS CLI with with the necessary permissions to deploy an AWS IoT stack in CloudFormation. I have an IAM User configured with a policy allowing it only to assume a single role that has the AWS managed policy IAMReadOnlyAccess attached, along with the below customer managed policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:PassRole",
                "secretsmanager:*",
                "iot:*",
                "cloudformation:*"
            ],
            "Resource": "*"
        }
    ]
}

(Note: This policy provides more access than the minimally required permission set to deploy/destroy a stack.)

I configure my CLI environment with the IAM user's Access Key and Secret Access Key.

aws configure

I then create a Named Profile to reference my Role's ARN.

 cat ~/.aws/config
...
[profile thingstack]
role_arn = arn:aws:iam::123456789012:role/ThingStack-Role
source_profile = default
region = us-east-2
...

(Note: replace the role_arn with your specific Role ARN.)

Then, clone this project and install the project prerequisites:

$ cd /Directory/Of/Choice
$ git clone https://github.com/edsw/ThingStack.git
$ python setup.py install

Lastly, create/edit the file cdk.json to include the default context variables used in provisioning the stack. I have intentionally left this file out of my repository since it contains my AWS IAM Role ARN. This JSON file includes the name of your AWS IoT Thing (thing_name), the JSON policy that applies to your Thing (policy_file), the IAM Role ARN that is assumed by the code (role_arn), and the AWS region where you are deploying IoT resources (region).

$ cat cdk.json 
{
    "app": "python3 app.py",
    "context": {
        "thing_name": "poolcontroller1",
        "policy_file": "policy.json",
        "role_arn": "arn:aws:iam::<account-id>:role/<role-name>",
        "region": "us-east-2"
    }
}

Deploy a Thing

To use the values from cdk.json and the Named Policy thingstack:

$ cdk deploy --profile thingstack

To specify alternatives on the command line:

$ cdk deploy --context thing_name=device1234 --profile thingstack

After Deploying a Thing

Once an AWS IoT Thing was provisioned, I needed to collect the necessary certificate details for my Arduino project. Note that in the below examples I specify the Named Profile I'm assuming via the --profile thingstack argument.

First, get the root certificate authority certificate under which all AWS IoT certificates are created.

$ curl -s https://www.amazontrust.com/repository/AmazonRootCA1.pem

Next, get the certificate provisioned by the AWS IoT service for your Thing.

$ IOT_CERT=$(aws cloudformation describe-stacks --profile thingstack --stack-name poolcontroller1 \
    --query "Stacks[0].Outputs[?OutputKey=='CertificateId'].OutputValue" --output text)

$ aws iot describe-certificate --profile thingstack --certificate-id $IOT_CERT \
    --query "certificateDescription.certificatePem" --output text

(Note: Replace poolcontroller1 with the name of your Thing)

Then, retrieve the private key for your certificate from AWS Secrets Manager.

$ KEY_SECRET=$(aws cloudformation describe-stacks --profile thingstack --stack-name poolcontroller1 \
    --query "Stacks[0].Outputs[?OutputKey=='SecretId'].OutputValue" --output text)

$ aws secretsmanager get-secret-value --profile thingstack --secret-id $KEY_SECRET \
    --query "SecretString" --output text | jq -r ".privateKey"

(Note: Again, replace poolcontroller1 with the name of your Thing)

P.S. You may also need to know your AWS IoT MQQT endpoint used to publish messages.

$ aws iot describe-endpoint --profile thingstack --output text

Notes

  1. To delete a stack, you must first set its certificate status to INACTIVE and re-run cdk deploy to update the stack. Then you can run cdk destroy [--context thing_name=] against it. In thingstack.py:
cert = aws_iot.CfnCertificate(..., status="INACTIVE")
  1. If you're using the above certificates in an Arduino project as I did, you'll need to specify the certificate details in your source code in a specific format. Append the following awk command to the above certificate printing commands in order to help with this formatting: | awk '{print "\"" $0 "\\n\" \\"}'

Resources

These sites were helpful in making this project successful:

To Do

  1. Define the minimally required permission set to deploy/destroy stacks with this project.
  2. Publish sister project with Arduino code DONE

thingstack's People

Contributors

edsw avatar

Stargazers

David avatar pinxian avatar  avatar  avatar grumpy maker avatar  avatar

Watchers

James Cloos avatar  avatar

Forkers

cmattatall

thingstack's Issues

Risk: over-authorization of AWS IoT policy

We are a security research team and we recently discovered that there is an over-authorization security issue with this project's IoT policies.
The affected files are as following:

1. ThingStack/README.md
2. ThingStack/policy.json

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.