Sharing Lambda Layers and Restricting Your Own Usage

I was recently reading the AWS documentation on controlling layer access and thought it felt a bit fragmented. That may be why you’re here too.

This post contains everything you need to know if want to share a layer with another account, an organization, or publicly. I’ll also show you how to restrict which layers can be added to functions in your account.

Five layered pancakes… get it? (Credit: Calum Lewis)

What Are Lambda Layers?

Feel free to skip this section if you’re already familiar with layers.

Layers were announced at AWS re:Invent in 2018 as a way of sharing a custom runtime, code, libraries, content, or dependencies. They let you keep your deployment package small and promote reuse.

A layer is simply a ZIP archive containing the files you want to share. You can add up to five layers to each function. They must be in the same region as the function, and the total unzipped size of the function’s deployment package and its layers can’t exceed 250 MB.

Layers are extracted and merged one-by-one into the /opt directory inside the function execution environment. This directory is read-only, but you can write up to 512 MB to /tmp, which I’ve written about previously.

Sharing Lambda Layers

Creating or updating a layer creates a new layer version with a unique ARN. When you add a layer to a function, you’re actually adding a specific version.

To add a layer version, you need permission to call GetLayerVersion on it, which you’ll usually get from an IAM policy.

When the layer is in another account, its resource-based policy must allow your account to use it, which is what we’ll discuss next.

Layer Version Resource-based Policies

Each policy contains zero or more permission statements that allow a principal to perform an action.

The principal can be a single account or all accounts. When the principal is all accounts, you can optionally specify an organization. As mentioned above, the action we care about is lambda:GetLayerVersion.

Adding Statements

Permission statements can be added using the AddLayerVersionPermission operation of the API and CLI. You can also use a CloudFormation AWS::Lambda::LayerVersionPermission resource.

Currently, there’s no way to manage these policies via the AWS Console.

Examples

Here are some CLI examples for version 1 of a layer named mySharedDeps.

Specific Account
 — 
Allow usage from the 123456789012 account.

aws lambda add-layer-version-permission
--layer-name mySharedDeps
--version-number 1
--statement-id specificAccountExample
--principal
123456789012
--action lambda:GetLayerVersion

Any Account
 — 
Allow usage from any account.

aws lambda add-layer-version-permission
--layer-name mySharedDeps
--version-number 1
--statement-id allAccountsExample
--principal *

--action lambda:GetLayerVersion

Any Account in an Organization
 — 
Allow usage from any account in theo-1234567890 organization.

aws lambda add-layer-version-permission
--layer-name mySharedDeps
--version-number 1
--statement-id allOrganizationAccountsExample
--principal *
--organization-id o-1234567890
--action lambda:GetLayerVersion

Removing Statements

Each statement is given a statement-id that can be used to remove it with the RemoveLayerVersionPermission operation of the API and CLI.

aws lambda remove-layer-version-permission
--layer-name mySharedDeps
--version-number 1
--statement-id specificAccountExample

Viewing an Existing Policy

New layers don’t have a resource-based policy until you add a permission statement. After you do, you can view the policy using the command below.

aws lambda get-layer-version-policy
--layer-name mySharedDeps
--version-number 1

Restricting Usage

You can restrict which layers can be added to your functions adding a condition element to any IAM policy that allows creating or updating functions.

This can prevent usage of layers published by other accounts, or accounts you don’t own. Another option is to limit usage to an approved set of layers that have been audited or tested, etc.

Let’s look at an example. The policy below restricts usage to layers published by the 123456789012 account that have names starting with test. You can find more information about condition elements in the documentation.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ConfigureFunctions",
"Effect": "Allow",
"Action": [
"lambda:CreateFunction",
"lambda:UpdateFunctionConfiguration"
],
"Resource": "*",
"Condition": {
"ForAllValues:StringLike": {
"lambda:Layer": [
"arn:aws:lambda:*:123456789012:layer:test*:*"
]
}
}

}
]
}

Do you use layers?

Recently, I published a post where I used a layer containing the .NET Core debugger (Remotely debugging .NET in AWS Lambda). Following re:Invent, AWS released the C++ Lambda Runtime which is intended to be packaged as a layer. There is also a curated list of Awesome Layers on GitHub.

I’d love to hear what other uses you’ve found for layers!


For more like this, please follow me on Medium and Twitter.