A New Open-Source Tool that Fills a Critical Serverless Security Gap 

author_profile
Ariel Shuper
Tuesday, Nov 22nd, 2022

One of the main attractions of moving software to the cloud has always been the “shared responsibility model,” wherein the cloud provider deploys, protects, and maintains the underlying infrastructure and execution environment and the customer takes responsibility for the environment within its containers. This model has become iteratively more seamless, with increasingly sophisticated tools emerging to improve operations and security on both sides.  

Serverless functions, such as AWS Lambda, have blurred these boundaries. These “pay-as-you-go” functions are maintained by the cloud provider but are executed as needed within the container. Despite their convenience and economy, the ephemeral functions have a catch: loss of visibility. It’s almost impossible to track vulnerabilities, and breaches are difficult to detect and remediate within the container environment. While containers have built-in security mechanisms to verify images with hashes (via a mission controller), serverless functions have no such protections. 

What are the options for serverless security?

Built-in solutions have deficiencies 

The hyperscalers have made efforts to fortify their side of the equation. For example, with AWS Lambda, developers can use AWS Signer to create digitally signed code packages for functions and layers. When a user deploys the code package, Lambda validates it before accepting the deployment. A code-signing configuration defines a list of allowed signing profiles and the actions to take if validation checks fail. But questions still remain. First off, there’s the issue of whether a developer is comfortable handing this important security task off to the cloud provider. What if someone on the provider side alters the function? As mentioned earlier, there’s no hash check to provide this assurance. Secondly, is validating at the deployment stage good enough?   

The concerns about these built-in solutions don’t stop there. While the code-signing mechanism may be a great starting point, it’s based on the AWS IAM roles and requires a dedicated profile for each function. What’s more, it only fires when the function is uploaded to the cloud account (for example, to an S3 bucket). In contrast, modern supply-chain security solutions start at the CI when the function is composed, prior to its deployment. 

These issues are far from trivial, considering that the number of attacks targeting the development pipeline—such as SolarWinds, Codecov, and Kaseya—have escalated in recent years.  

There’s a better way 

Cisco’s newest open-source project—FunctionClarity, part of the OpenClarity suite of cloud-native security tools—fills in the serverless security gap. Instead of waiting until deployment to validate serverless functions, it supports keyless signing within the CI pipeline with sigstore, part of a larger framework supported by the Open Source Software Foundation. Sigstore leverages Fulcio (root certificate authority) to generate short-lived certificates and Cosign to sign the functions. Cosign works with traditional key-pair approaches (public/private) and can also be used to sign images or blobs (source code, Helm charts, infrastructure-as-code, etc.). Sigstore employs Rekor as a transparency log to enable verification and provenance. This enables developers and DevOps engineers to sign their code, regardless of whether it is a severless function or a deployment file (such as AWS’ CloudFormations templates).  

Workflow Diagram

FunctionClarity invokes a validation function to ensure that the new or updated serverless function is signed (via hash or Rekor) and uses the output to either allow or block the function’s invocation process.  

This serverless security solution has numerous benefits, including being cloud-agnostic and extending signing to the function’s deployment files. 

Below is the basic workflow: 

  1. Deploy FunctionClarity, using its validation function in the target cloud account (a one-time operation). This will scan and verify new functions when created or updated in the target account. 
  2. Sign functions with FunctionClarity’s command-line interface (CLI) to sign the function code or image in the user’s environment and then upload it to the target cloud account. 
  3. Deploy the serverless function using the signed function code/image. 
  4. Verify functions using FunctionClarity’s verifier. Again, this is triggered when user functions are created or updated and performs the following:
    • Fetches the function code from the cloud account 
    • Verifies the signature of the function code image or .zip file 
    • Follows one of the actions below, based on the verification results:
      • Detect marks the function with the verification results 
      • Block tags the function as “blocked” if the signature is not correctly verified (otherwise it does nothing) 
      • Notify sends a notification of the verification results to an SNS queue

The diagram below shows the deployment architecture in AWS/Lambda functions: 

FunctionClarity Workflow Diagram

Getting started 

Follow the steps below from your terminal to install FunctionClarity in your AWS account. You’ll be executing the following commands from the folder where the FunctionClarity tar file is located. During the deployment process, the validation function will be deployed in your cloud account, triggered by the creation or modification of a serverless function. A configuration file will also be created locally, in ~/.fc, with default values that will be used when signing or verifying functions, unless specific settings are configured with command-line flags. 

  1. Run the command ./function-clarity init AWS 
  2. When prompted, enter the following details: 
function-clarity init AWS_1
  1. The installation process will continue until it is complete. It will return the following: 
function-clarity init AWS_2
  1. Use the command below to sign a folder containing function code, then upload it to the user cloud account. 
function-clarity init AWS_3
  1. Deploy a function or update function code by using the AWS CLI to deploy a signed Lambda function to your cloud account or to update Lambda code in the account. 
     
  2. Automatically verify on function creation or update events. If the verifier function is deployed in your account, and if it meets the filter criteria for any function, the event will trigger it to verify the new or updated serverless function. It will follow the post-verification action (detect, block, or notify). If the action is detect, the function will be tagged with the FunctionClarity message that it is verified. See the example below:  
function-clarity init AWS_4
  1. If the action is block, the function's concurrency will be set to 0 and the function will be throttled, per below: 
function-clarity init AWS_5

Visit FunctionClarity’s GitHub repository to download the application or contribute to its development. And don’t forget to swing by our booth (2411) at AWS re:Invent to say hello! 

Popup Image