Following on from my previous post I look further into developing on Serverless Framework, specifically around logging, function invocation and permissions.

Logging

Functions in Serverless Framework log to CloudWatch and these logs can be found by navigating to your function in the AWS Console and then to Monitor > View logs in CloudWatch. It’s also possible to see those same logs locally:

serverless logs --function parseFeed [--tail]

This command will print a bunch of latest logs to your console and --tail will watch for further logs and print them when they arrive.

Invoking Functions

Functions can be invoked via AWS Console > Lambda, but you can also invoke them directly from your command line too. The serverless-offline plugin is one way mentioned in my previous post, however Serverless can invoke these natively too. The following command will invoke a deployed function:

serverless invoke --function parseFeed

And the command below will package and invoke a function locally, without needing to deploy.

serverless invoke local --function parseFeed

Permissions

When invoking functions locally with either invoke1 or the offine plugin2 your default AWS credentials for AWS will be used. Considering this is likely the profile you deploy with, these credentials will have much more permissions than the execution role your deployed lambda will have. This means that invoking functions locally might succeed due to your local AWS profile’s permissions, and then fail once deployed due to limited permissions on the deployed execution role.

By default, the execution role in Serverless Framework is shared across all lambdas, and only includes permissions specific to logging to CloudWatch:

- logs:CreateLogStream
- logs:CreateLogGroup
- logs:PutLogEvents

If we expect a function to be able to write to S3, our deployed function will need a permission to do that, and we can configure that permission across all lambdas like so:

provider: {
  name: "aws",
  iam: {
    role: {
      statements: [
        {
          Effect: "Allow",
          Action: ["s3:PutObject"],
          Resource: "arn:aws:s3:::${self:custom.bucketName}/*",
        },
      ],
    },
  },

Prior users of Serverless might be more familiar with iamRoleStatements syntax, however this has been deprecated. If for some reason it is desirable to have separately configured permissions per lambda, then a plugin is available for this.