Haskell in AWS Lambda

2018-03-08

As you know, I’ve blogged a fair amount recently about calling AWS services from Haskell. I’ve also demonstrated a close-to-minimal Haskell program that can itself run inside AWS Lambda using the serverless-haskell package. Since those experiments, I’ve tried to get my AWS Lambda program to something useful and have, unfortunately, run into a wall. Today, I’m going to talk about some of the issues I’ve encountered:

Unable to call STS APIs

First, I tried to extend my HLambda program to call the STS GetCallerIdentity API just to dump my account ID to the log during executing of my Lambda function. This didn’t work. My original Lambda function used the AWSLambdaBasicExecutionRole security role. I tried increases the privileges granted to my function, even going so far as adding full AdministratorAccess to my function’s role. None of this allowed my call to this API to succeed. In fact, the call seems to “go nowhere” and never returns. Unable to debug this, even with some metrics from X-Ray, I abandoned this.

Briefly able to call SSM APIs, until I couldn’t

Next, I tried calling various SSM APIs such as GetParameter and PutParameter after adding the AmazonSSMFullAccess policy to my role. At some point this worked. I even had my function successfully reading and writing SecureString parameters. And, then, it mysteriously stopped working. Unfortunately, I was not able to roll my program back to a working state. Nothing I was able to do to tweak my security policy etc. seemed to have any effect.

Unable to call web APIs

I then thought I’d pare things down to the bare minimum. I was able to write to the CloudWatch log simply by writing to standard output using putStrLn. However, presumably due to the way the logs are buffered, not all of my messages would be visible in CloudWatch. I, therefore, created a logMessage function to ensure that the message is proactively flushed:

That got things to reliably show up in the log.

I then thought I’d build on that my building a minimal HTTP client using Req:

This, unfortunately, suffered from the same affliction as my attempts to call into AWS APIs: the call simply doesn’t not return. I’m wondering if, somehow, my AWS Lambda environment does not have access to the Internet, though I haven’t been able to positively confirm this one way or another.

So, I’m stumped.

What I’m trying next

It’s possible that I’m running into difficulties because I’m building my program inside an Ubuntu 16.04 virtual machine running on VirtualBox instead of the Amazon Linux OS running inside the AWS Lambda execution environment. Perhaps, I am generating binaries that are incompatible in some way or failing due to a missing native function at runtime.

So, I decided to try to emulate this environment as closely as possible…

By the way, I avoided following the official instructions, because I’m lazy.

I then proceeded to get a Haskell build environment set up with Stack and other dependencies:

I’ll let you know how this goes!

Tags: Haskell, AWS, Lambda, Amazon Linux

All content © 2018 Richard Cook. All rights reserved.