Dissecting Serverless Stacks (I)
This content is more than 4 years old and the cloud moves fast so some information may be slightly out of date.
Dissecting Serverless Stacks (I)
This post establishes the base for a small series on how to create Serverless based Lambdas which can be deployed in environments without IAM privileges or where the sls
command cannot be used at all.
As you are probably aware, the Serverless Framework is one of the best established ways of writing serverless architectures and deploy them on e.g. AWS. It provides a handy way to have everything related to a project centralized, be it the source code or the CloudFormation/IAM resources. With easy commands like sls deploy
you can then create or update your code in a consistent fashion.
Depending on your type of organization you might hit some problems, though. It is good practice to not have the same person create security privileges and use them, also called “Separation of Duties”. As all Lambda functions on AWS need their share of IAM, this makes deploying with the built-in methods hard. One would need a way to still have everything in one project but cater to this particular organizational structure.
It can get even worse. After you basically finished your project, it turns out you won’t have any AWS permissions at all and need to hand it over to somebody else for deployment. And, that is not too far-fetched, that person does not have any interest in installing the sls
command but insists on getting some CloudFormation YAML files and a ZIP with the code.
With some tweaks, it is possible to have one SLS project but offer all three deployment styles:
all-in-one
, the standard SLS wayiam-plus-sls
, for a CloudFormation stack but still using SLS as a developerbits-and-pieces
, for handing over to another party.
This blog post series will explain how to get there, so let’s begin.
Starting off and Cleaning up
For our journey, we will talk about a small SLS project and concentrate on the serverless.yml
file as most problems can be solved within this file. As the following posts will use a syntax slightly different to most of these files I have seen in the wild, this post will simply introduce our point to start with and tidy it up for the things to come.
As I am notoriously promoting Ruby, this will be a Ruby based Lambda.
service: fancy
provider:
name: aws
runtime: ruby2.5
region: eu-west-1
iamRoleStatements:
- Effect: Allow
Action: s3:GetObject
Resource: 'arn:aws:s3:::importbucket/*'
package:
exclude:
- package*.json
- node_modules/**
functions:
fancy:
description: Our fancy example Lambda
handler: src/handler.main
As you can see, we have the usual iamRoleStatements
block in here which will be used for all functions we are definiing in our project. Coming from a lot of trainings where I promote the Least Privilege Principle, I find this mildly irritating and would suggest reworking this. The SLS documentation specifically talks about the possibility to attach policies directly to the functions, which has to be done by adding it into the resources
section:
service: fancy
provider:
name: aws
runtime: ruby2.5
region: eu-west-1
package:
exclude:
- package*.json
- node_modules/**
functions:
fancy:
description: Our fancy example Lambda
handler: src/handler.main
role: fancyRole
resources:
Resources:
fancyRole:
Type: AWS::IAM::Role
Properties:
RoleName: MyfancyRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: allowS3
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Effect: Allow
Action: s3:GetObject
Resource: 'arn:aws:s3:::importbucket/*'
Be careful though! While the common iamRoleStatements
shortcut automatically adds the ability to our Lambdas to write logs, this syntax does not. Hence, we have to include the logs:
statements here.
This does not look very convenient, but I promise to make things much cleaner in the next post