Deploying resources with IaaC using Lambdas

Have you ever wonder if it’s possible to create, manage and deploy infrastructure as a code using AWS CloudFormation through lambdas?

But…Why?

Some of the benefits i thought while researching this route were:

  1. Granular control of what is being created, modified or deleted on your infra.
  2. Easier to migrate to another vendor.
  3. Faster to deploy multiple resources at the same time.
  4. Having all wrapped inside AWS stacks.

The initial approach

Creating a resource on an AWS account with a Lambda came with some ideas. The one I tested follows this path:

  • A json template file stored inside a bucket.
  • One lambda will run and read the json file inside the bucket
  • The lambda will โ€œtalkโ€ with AWS CloudFormation and send some parameters to create a stack. One of those parameters will be the json template.
  • AWS CloudFormation will create the resources specified on the json template.

This is how all of the above looks.

Testing time!

First you need to put the json template inside a bucket. Feel free to copy the one i used here:

https://github.com/wifiwolfg/lambda-iaac/blob/main/s3template.json

This will create a stack with a public s3 bucket ready to host a website. This file was saved as s3template.json inside a s3 bucket. The parameter you will need is the object URL.

The Lambda

For this test I created a Lambda on python. You can download it here:

https://github.com/wifiwolfg/lambda-iaac/blob/main/lambda-params.py

Or if you prefer copying it from here, this is how it looks:

import json
import boto3
import os
from datetime import datetime
from urllib.parse import urlparse

template_url = "https://yourlink.s3.amazonaws.com/s3template.json"

def launch_stack():
  cfn = boto3.client('cloudformation')
  current_ts = datetime.now().isoformat().split('.')[0].replace(':','-')
  stackname = 'stack-test-from-lambda-s3' + current_ts
  capabilities = ['CAPABILITY_IAM', 'CAPABILITY_AUTO_EXPAND']
  try:
    stackdata = cfn.create_stack(
      StackName=stackname,
      DisableRollback=True,
      TemplateURL=template_url,ud
      Capabilities=capabilities)
  except Exception as e:
    print(str(e))
  return stackdata  

def lambda_handler(event, context):
  print("Received event:")
  stack_result=launch_stack()
  print(stack_result)

Important: For this to work, when I created the lambda, the role attached to it needed permissions to read S3 resources and writing actions to CloudFormation resources.

You can notice the Template_URL pointing to the s3 object URL that contains the json.

Results

We can go to CloudFormation and see the stack was successfuly created.

Awesome! It created the resources.

Then if you go s3, you will be able to find the new bucket.

Bucket is there

Conclusion

We are able to have a lambda which can be triggered in many ways and then it will create resources using CloudFormation and have IaaC along with it.

There are lots of use cases where this can be very helpful. How do you think you can use this?

Written by

Rodrigo Mencos

Hi there! I’m Rodrigo, born and raised in Guatemala and currently a DevOps engineer with love for coffee, infosec, technology and outdoor exploration.


Hola! Soy Rodrigo de Guatemala. Actualmente soy Ingeniero DevOps a quien le encanta el cafe, la seguridad informatica, tecnologia y explorar el mundo.