Accessing shadow documents on AWS Greengrass

AWS Greengrass is an amazing product bringing AWS IoT to the edge but also cloud development tools and the Lambda execution environment. This is going to be one of many short posts giving tips on using AWS Greengrass and accessing some of the basic functionality.

What are Device Shadows

If you’re worked with AWS IoT Core before you’ll know that shadows are copies of the state information for a device. They are extremely useful for tracking the status of devices without actually having to query a device directly. They are also critical in all command and control situations allowing us to change state in a deterministic fashion.

Shadows on AWS Greengrass

With AWS Greengrass you can have local shadows and those can also be synchronized with the cloud so that devices or systems that are remote or cloud based can still access and change shadow information.

So how to we access these shadow documents within our Lambda functions on the core? There is an SDK for the core that you deploy as part of your Lambda function however, it is not obvious how to actually get a shadow and more importantly, that the shadow data is actually double stringified! This is a common pattern with AWS, payloads are JSON stringified but so is the actual response object from a query.

Here is a short code snippet that fetches the shadow in Python:

client = greengrasssdk.client('iot-data')
shadowRaw = client.get_thing_shadow(thingName = "name_of_your_greengrassDevice")
shadowData = shadowRaw["payload"]
shadow = json.loads(shadowData)
speed = shadow["state"]["reported"]["your_attribute"]

You can see from the above, we can now access the “reported” or “desired” state of our shadow.

Updating the shadow

Here is another code snippet to update the shadow:

client = greengrasssdk.client('iot-data')
shadowData = client.get_thing_shadow(thingName = "name_of_your_greengrassDevice")
shadow = json.loads(shadowData['payload'])
shadow["state"]["reported"]["speed"] = event['speed']
shadow["state"]["desired"]["speed"] = event['speed']
client.update_thing_shadow(thingName = "name_of_your_greengrassDevice", payload = json.dumps(shadow))

In the above example, we’ll setting the speed value of our device in both the reported and desired sections of the shadow. This is just an example, usually you’re updating desired and the device updates reported.

Hopefully this helps those working with AWS Greengrass.

Building a Docker Image with an Android Emulator on AWS

Let’s just say one day you wake up and ask yourself, could I see a desktop inside a running Docker container? Could I then take that a step further and see an emulator (basically another step of virtualization)? Well then you’re in luck as that is exactly what we’re going to do.

The Original Problem

What leads us to do this? Well I had someone ask how they could scale out testing Android applications in the cloud. My initial thought was to just spin up some EC2 instances pre-configured with the emulators which would work fine but managing this get’s cumbersome when you start looking at large numbers.

The AWS/Docker Solution

A good way to scale this kind of solution is using Elastic Beanstalk with ECS. ECS works hand in hand with Docker images and Elastic Beanstalk and will help manage a fleet of test servers. To get our above solution working we want to setup the following:

  • Create a docker image with NoVNC and support for GLX so we can emulate the video card for the Android emulator.
  • Setup a android virtual device (AVD).
  • Bundle up our Docker image and keep it in a repository such as Docker Hub.
  • Use Elastic Beanstalk to launch our custom AMI with our Docker image.

I’m not going into the specifics of how the Docker image was built, you can read through the Dockerfile that is included in both the Github repo or the Docker Hub repo.

Please note that I’m using the AUFS drivers for Docker and not the default Devicemapper. Devicemapper will limit you to 10GB images and a 100GB total bundle for your images. Althrough you can find some information on increasing these values, they just don’t work! At least at the time of writing ;) You will suffer needlessly if you try and your images pushed and pulled via Docker Hub will also incur issues.

When you use the AUFS drivers your Docker image gets full access to the host disk space. You don’t have to limit an image to specific sizes. Unfortunately the AWS Linux used for default Elastic Beanstalk deployments etc doesn’t support AUFS so I’ve been using the Ubuntu 14.04 AMI in the AMI Marketplace.

Building The Docker Host

Here are the instructions for building a compatible Docker Host, these are mirrored again on the Github repository.

Here is the link for the repo,

  • Setup Ubuntu 14.04 – if on AWS use the Ubuntu Marketplace AMI.
  • Make sure your host VM has at least 40GB of space, this image uses ~25GB when running.
  • With AUFS Docker can use the entire host file system for image space vs devicemapper which is the docker default but has terrible 10GB limits and increasing it will cause you problems.
  • Run the follow commands to install the aufs version of docker.
sudo apt-get update
sudo apt-get -y install linux-image-extra-$(uname -r)
sudo sh -c "wget -qO- | apt-key add -"
sudo sh -c "echo deb docker main\ > /etc/apt/sources.list.d/docker.list"
sudo apt-get update
sudo apt-get -y install lxc-docker
  • Setup docker to work without sudo
sudo service docker start
sudo usermod -a -G docker ubuntu
  • Test Docker – don’t fret if it throws an error, see next step
docker info
If that didn't give the information screen do the following
(remember skip this step if docker info already works)
sudo docker -d
sudo service docker start
docker info

Build The Docker Image

Next we need to build the Docker image. This is done using a Dockerfile and supporting resource files. The hard work of making a working Dockerfile has already been completed and this is the file you edit if you want some extra goodies installed for a new image.

  • Start by cloning the repository into a folder on your running Docker host.
  • git clone
  • Change folder into the android-emulator folder or whatever you called it.
  • Run the Docker build command to create a new image, note the image name “android-emulator” is just what I called it, if you’re using Docker Hub you’ll want to use your username + /android-emulator.
  • docker build -t android-emulator .

Using The Image

The build process takes awhile but once completed you should see your image by running docker images. There you’ll see all local images.

The run this new image just use: (if you gave the image a different name then change it below)

docker run -dt -p 6901:6901 android-emulator

You’re mapping port 6901 on the container to 6901 on the host, the container port is always 6901 but your host port can be whatever you want to use and is open on your firewall. Since this was built on AWS my security group allows this port.

You can now surf to the Docker host public IP on port 6901 and you’ll see a list of files, pick vnc_auto.html and you can now login via NoVNC to see the desktop, running in the container, running in a VM :)

The default vnc password is “vncpassword” – so make sure you change this or limit access to just your IP!

Final Steps

Currently the script doesn’t install the Android SDK although all dependencies are already installed for you. To actually get an emulator working following these steps:

  • Once connected over NoVNC open the browser and download the Android SDK.
  • Extract the SDK and run the Android tool.
  • Use the Android tool to install your required SDK API version and Emulator support.
  • You can now run AVD’s etc as desired.

Now that everything is working you can push this image to Docker Hub and use it from EB/ECS or just run manually.

I’ll do another post on exactly how to run a custom image in EB and ECS next!

The Shortcut!

You don’t want to do all this work?? – ok! There is a Docker Hub image with everything above – you’ll still need to setup a Docker host to run the image but that is really pretty straight forward, instructions are in the repo.


Fixing invalid signatures on the AWS API Gateway

Here are some things I learnt the hard way while working with the API Gateway and trying to authenticate users hitting the API. Something by the way that everyone should be doing! Far too many open end-points out there and the APIG (Amazon API Gateway) gives you IAM control or a shared API KEY. This article is focused on getting IAM working: Another post will cover the details of Cognito/IAM and the APIG.

What goes wrong?

To protect my end-points I wanted to use IAM so that the keys used by the end user would expire every 60 minutes and I’d also know exactly who was using the service. I turned on IAM under the authorization of each of my APIG methods. We’ll assume you have valid AccessKey, SecretKey and SessionTokens obtained via the AWS SDK. I started to run into error messages that all looked something like this:

  • Invalid Signature.
  • The request signature we calculated does not match the signature you provided.
  • The Canonical String for this request should have been ….
  • (You’re using a GET request)
  • Any messages related to invalid tokens, sessions etc are tied to issues around how you authenticated and will be covered elsewhere.

The solution

As of this writing I believe this issue lies within the APIG itself. The gateway is making an assumption that when using GET requests that the body is empty and I mean empty! not {}. If you read over the code in the sigV4Client.js you’ll see that an undefined body also gets changed to {}. When the payload signature is calculated against {} it won’t match the server signature which is being calculated against ”. To fix it change your sigV4Client.js – the method buildCanonicalRequest should read as follows:

function buildCanonicalRequest(method, path, queryParams, headers, payload) {
        if (method == 'GET' || method == 'get') payload = '';
        var result = method + '\n' +
            buildCanonicalUri(path) + '\n' +
            buildCanonicalQueryString(queryParams) + '\n' +
            buildCanonicalHeaders(headers) + '\n' +
            buildCanonicalSignedHeaders(headers) + '\n' +
            return result;

Although you’re allowed by the HTTP specification to pass data in a GET request you really shouldn’t be :) but the {} as a value is acceptable..


I’ve found it is worth sticking it out with these new technologies as I believe this is the direction backend development is going to take, this along with container services such as Docker will quickly replace the typical VM/Instance model of deployment.

Getting started with the AWS API Gateway

I’m super exited to get started with the brand new service from Amazon Web Services, the API Gateway – AWS API Gateway

The API service is an abstraction to your existing and internal API’s providing not just a front-end service to scale your offerings but also supports automatic generation of SDK’s for using your API! Right out the gate we’ll start by testing our generation of the mobile (iOS) SDK generation to support the expanded SafeChat API v2.

I’ll be focused on SDK support but also scaling and API protection offerings such as, making sure my API end-points aren’t being attacked or flooded.

Stay tuned!