Introducing Lambda Tools: a new framework for deployment to AWS Lambda

Lambda Tools is a new project that I’ve been working on over the past few weeks or so. It is a build and deployment toolkit, written in Python, to make it easier to work with AWS Lambda functions. It started out as a user story in our backlog at work but since then it’s grown into a full blown open source project with a life of its own.

The “serverless” model offered by AWS Lambda is a useful and potentially cost-effective one, especially for scheduled tasks that only need to run every so often and don’t require a lot of resources. The “free tier” doesn’t expire at the end of your initial twelve month trial, which is an added bonus.

The downside is that it can be tricky to work with. If your function requires additional libraries, it starts to get a bit more complex, and if any of these are written partly in C and require special compilation, things can get pretty messy. On top of that, you will want to write unit tests for your functions and set up some sort of Continuous Delivery pipeline for them.

Lambda Tools includes several features to make these things easier. For example, it gives you an option to build your function in a Docker container to avoid these messy “invalid ELF header” errors. You configure it simply by creating a YAML file called aws-lambda.yml, which might look like this for example:

version: 1

functions:
  hello_world:
    runtime: python3.6
    build:
      source: src/hello_world
      requirements:
        - file: requirements.txt

    deploy:
      handler: hello.handler
      role: service-role/NONTF-lambda

      description: A basic Hello World handler
      memory_size: 128
      package: build/hello_world.zip
      region: eu-west-2
      timeout: 60

      tags:
        Account: Marketing
        Application: Newsletters

Here are some of the other ideas that I’m thinking of implementing for it:

  • A unit test runner
  • Support for Python 2.7
  • Support for languages other than Python (.NET, Node.js, and so on)
  • Integration with Terraform:
    • The ability to plug it into Terraform’s external data source provider
    • The ability to read configuration from stdin
    • A scaffolding engine to generate Terraform modules on the fly
  • Integration with triggers such as CloudWatch cron jobs, API Gateway, and so on
  • A full-blown sample application
  • The ability to include or exclude specific files when building your package

At the moment it only supports Python 3.6 but nevertheless it is in a usable state. You can install it using pip install lambda_tools and it includes full instructions in the readme file on the GitHub repository. Additionally, if you’re interested in getting involved with its development, feel free to fork the project and send me a pull request or three. If it’s anything more complex, raise a ticket on the GitHub issue tracker and we’ll chat about it there.

Necessary and sufficient conditions

Take a look at these two statements. Are they both saying the same thing?

  1. “If you are using HTTPS, then your website is secure.”
  2. “If you are not using HTTPS, then your website is not secure.”

In actual fact, they are not. Furthermore, only the second statement is true: the first statement is false.

The first statement is an example of a sufficient condition. If it were true, all you would need to do to secure your website would be to install an SSL certificate and you’d be done.

The second statement, on the other hand, is an example of a necessary condition. There are, of course, other things you need to do to ensure that your website is secure: for example, take care to avoid SQL injection and cross-site scripting attacks, keep your servers patched and up to date, and so on. But you still need to use HTTPS in addition to all these. If you don’t, your site will be vulnerable to a man-in-the-middle attack.

You can see the difference if I draw up a truth table for a sufficient condition:

Sufficient condition Other stuff Secure?
No No No
Yes No Yes
No Yes Maybe
Yes Yes Yes

On the other hand, a necessary condition looks like this:

Necessary condition Other stuff Secure?
No No No
Yes No Maybe
No Yes No
Yes Yes Maybe

Some conditions can be both necessary and sufficient. In this case, the truth table looks like this:

Necessary and
sufficient condition
Other stuff Secure?
No No No
Yes No Yes
No Yes No
Yes Yes Yes

A necessary and sufficient condition can be written as “if and only if.” This is sometimes shortened to “iff.”

Insufficient does not mean unnecessary.

The most common misunderstanding that people have about necessary and sufficient conditions is the mistaken belief that one implies the other. Or that a lack of one implies a lack of the other.

  • It is possible for conditions to be sufficient but not necessary.
  • It is possible for conditions to be necessary but not sufficient.

Take, for example, this comment:

Google is just a bully because it is so big. It can go f*** itself. A standard webpage is not insecure and the use of SSL doesn’t make it secure either. Maybe everyone forgets that when SSL certs were comprised. I do work on e-commerce sites and I have seen clients who sites got hacked, not because of lack of SSL, but because of bad code on their backend. The hackers proceeded to add code so they would get emailed the credit card info after it was submitted. The user would never know, because the big green icon in the browser said it was secure. The whole thing is just a way for companies to make money.

This commenter correctly realised that SSL is insufficient but he then assumed that this means that SSL is therefore unnecessary. This is of course incorrect. SSL may be insufficient, but it is very, very necessary.

Unfortunately, in the world of IT security, there are plenty of necessary conditions. But there are no sufficient ones.

Programmatically starting an AWS instance with an encrypted EBS volume attached

I had to start some EC2 instances programmatically from inside an AWS lambda function. My code looked something like this:

import boto3

def handler(event, context):
    client = boto3.client('ec2')
    client.start_instances(InstanceIds=['i-0123456789abcdef0', ...])

This worked fine when I ran it from the command line, but when I ran it from inside the lambda, one particular instance stubbornly refused to start, even though the lambda ran without errors.

It turned out that the problem was a permissions issue. This particular instance had an additional encrypted EBS volume attached. The call to start_instances() was failing silently.

To fix this, make sure that the role under which your code runs is granted the kms:CreateGrant permission.

It took me a bit of trial and error to figure out which permission to add, but I wanted to make sure I got this one right. You should never give your code any more permissions than the bare minimum it needs in order to do what it needs to do. Unfortunately, figuring out exactly which permissions your code needs to run can sometimes be a bit of a challenge…

New blog on creation and evolution

In the past few months I’ve written a couple of posts here on my blog about my forays into the creation and evolution debate. However, since I’d rather keep this blog focused on subjects related to my professional work with software development, DevOps, and this Parliament-as-a-service startup that I’m working at, I’ve started up a separate blog to act as a brain dump for everything that I’ve learned about the subject over the past couple of years.

At the moment I’ve got it set to publish a new post every Monday every week through until September.

In case you hadn’t already figured out, my position on the matter is 100% evangelical Christian but also 100% old-earth. I’m sorry folks, but the earth simply isn’t six thousand years old, it’s as simple as that. The Bible does not require it, and the evidence does not support it and can not be re-interpreted to support it without descending into absurdity or dishonesty or both.

I’m generally tending to focus more on the physical sciences side of the debate — dating methods, geochronology, astronomy, and so on. Not being a biologist, I don’t tend to have much to say about evolution itself. Not unless you’re making claims about it that are blatantly clueless, such as that it’s “only a theory,” or that it contradicts the Second Law of Thermodynamics, or that mutations can’t produce new information, or that there are no transitional fossils, or silly straw man arguments about cats not turning into dogs. All I ask is that you make sure that you know what you are talking about, and that your facts are straight.

Continuous Retrospectives are not a substitute for retrospective meetings

About a year ago, I proposed to our team that we should adopt a continuous approach for our retrospectives. One of the questions that came up was whether this should be a replacement for regular weekly (or once per sprint) retrospectives.

After a year, I’ve come to the conclusion that you probably need both.

I came up with the idea of a continuous retrospective to fix a specific problem with regular retrospectives: halfway through the sprint, you realise that something is a problem, but by the time you get to your end-of-sprint retrospective, you’ve completely forgotten about it.

Another advantage of continuous retrospectives is that, in theory, they can shorten the turnaround time for resolving problems, so points of friction don’t linger throughout the sprint.

However, I’ve found over the past year that continuous retrospectives have one particular flaw: they can easily lose momentum. It’s all too easy to get complacent about continuous improvement, to end up having your retrospective board sitting neglected in a corner with nobody ever adding anything to it, and before you know what’s happened, you’ve gone from sub-optimal retrospectives to no retrospectives at all.

If you’ve bought into the 37 Signals/Basecamp/whatever they’re called this week “meetings are toxic” ethos, the idea of having one less meeting may sound attractive. However, the ceremony and formality involved in regular retrospective meetings gives them an inertia that keeps them going. It forces each team member to be regularly thinking about what is going well and what isn’t. And it provides a forum for the issues to be discussed in more detail rather than coming up with off-the-cuff solutions that may not be properly thought out.

Continuous retrospectives can definitely offer considerable value. But don’t ditch your end-of-sprint (or weekly) retrospectives. Rather than doing one or the other, you’ll most likely get the best value out of doing both.