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 way
  • iam-plus-sls, for a CloudFormation stack but still using SLS as a developer
  • bits-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

Similar Posts You Might Enjoy

Dissecting Serverless Stacks (IV)

Dissecting Serverless Stacks (IV) After we figured out how to implement a sls command line option to switch between the usual behaviour and a way to conditionally omit IAM in our deployments, we will get deeper into it and build a small hack on how we could hand over all artefacts of our project to somebody who does not even know SLS at all. - by Thomas Heinen

Dissecting Serverless Stacks (III)

Dissecting Serverless Stacks (III) The third post of this series showed how to make IAM statements an external file, so we can deploy that one but still work with the sls command. It still involved commenting out things in the configuration, so this post will show how to solve that issue. - by Thomas Heinen

Dissecting Serverless Stacks (II)

Dissecting Serverless Stacks (II) With the output of the last post of this series, we established the base to be able to deliver a Serverless application independent of its needed IAM privileges. So let’s see how this will work out. - by Thomas Heinen