AWS Lambda is a serverless compute service from AWS. Serverless cloud services enable teams to quickly build applications, APIs and services without managing a lot of traditional infrastructure such as servers and virtual machines (VMs).
Since most of the traditional security practices do not fit into the serverless model, serverless application security demands a paradigm shift. In this article, we shall discuss key security best practices that can help your team develop secure serverless applications on Lambda.
About Serverless and AWS Lambda
To understand the security aspects of this service, teams must be familiar with some basic concepts about Lambda.
Lambda executes application code in Lambda functions. As a developer, you create an application as a set of Lambda functions and deploy in AWS Lambda. AWS takes care of provisioning the compute resources required for executing these functions. Lambda completely relieves you from the burden of managing infrastructures such as virtual machines and networks.
Each Lambda function can be triggered by an event such as an HTTP request, a change in a database record, an email or SMS etc. Once the event is triggered, the function code gets executed. The code may interact with other AWS services such as databases and then sends an output.
AWS Shared Responsibility Model
When your organization deploys software applications on VMs and containers in the traditional software architecture, you are also responsible for the security of this underlying compute infrastructure (such as encrypting EC2 volumes and updating and patching OS and software). If your team chooses to build and architect applications in AWS Lambda, some of these infrastructure security responsibilities shift to AWS.
However, this does not mean that Lambda completely releases you from the responsibility of security. While AWS takes care of many infrastructure security standards, you are still responsible for the application security and specific cloud configuration settings according to the AWS shared responsibility model.
Consider the following Shared Responsibility Model as it relates to Lambda:
With AWS Lambda, your team is effectively responsible for security in software code, resource configuration, and access management. Your organization is responsible for Lambda security configuration including:
- Application code and security
- VPC and networking settings
- IAM permissions and roles
- Access to the Lambda deployment process/APIs
- Function security related to other cloud services
Now, let’s explore some best practices that you can follow to implement security on these aspects.
Grant Least Privileges
Following the ‘principle of least privilege’ is one of the most important security considerations for Lambda. When providing access to Lambda functions, you should grant the minimal number of privileges to your functions that are necessary for users to perform their intended actions and no more.
Lambda is integrated with AWS IAM so you can use IAM policies to grant privileges to Lambda functions via execution roles. An execution role is an IAM role that defines what AWS resources can be accessed from a Lambda function. According to the concept of least privileges, you must ensure that each Lambda function is configured with an execution role that allows access only to the essentially required resources. Also, the execution role must allow only the essential operations to be executed on those resources. As an example, a function can be allowed with read-only permission to an S3 bucket.
IAM can also define resource-based policies for a Lambda function. A resource-based policy defines which AWS services are authorized to invoke a function. You must ensure that this permission is also granted only to essential AWS resources for each function. Dash ComplyOps can help identify and resolve permission issues across your AWS environment.
Consider taking the following steps to limit access:
- Set granular IAM permissions for Lambda functions.
- Limit user access via IAM permissions to only necessary resources and operations.
- Remove unused or outdated IAM Users, Roles and Permissions.
- Periodically review and adjust IAM permissions.
Using the least privileges may be harder to achieve than it seems. From the developers’ perspective, it requires additional planning and considerations. It is always easier for a developer to allow maximum privileges for all the functions at the development phase, and configure individual privileges at the final stage just before the product release. Such practices where security is an afterthought cannot implement the concept of least privileges properly.
A serverless application can have thousands of functions where setting individual policies and testing may be cumbersome at the final stage of the development. It is important that functions should be designed with granular permissions rather than granting large groups of permissions. Security-centric development practices like DevSecOps must be adopted from the early stage of development for serverless software projects, to make the concept of least privileges effective.
Protect Application Data and Secrets
Lambda allocates an execution environment for each function that is invoked. The Lambda execution environment provides a file system at ‘/tmp’ for application developers to store temporary data related to the execution of a function.
An execution environment is never shared across multiple user accounts, so provides a safe storage location for such application data. However, AWS does not recommend storing security-sensitive data such as payment data, customer information in the Lambda execution environment.
Instead of using the storing secrets in a function’s runtime, you should consider EC2 Systems Manager Parameter Store or Lambda Environment Variables with Encryption Helpers to securely store such sensitive application data.
Design Granular Lambda Functions
Serverless technologies like Lambda erode the concept of perimeter security. This can be a plus point as the developers are able to focus more on securing the application code. Consider the following, a function is the basic building block in Lambda. It contains the code that is executed at the function invocation. You are entirely responsible for the security of this code.
Each Lambda function is granted privileges separately. If you create a function that has multiple responsibilities, you have to allow a wide range of privileges to that function. This can expand the range of potential threats. By keeping the functions granular, you can limit their privileges so that surface of attack is reduced.
Developers should design functions for a specific purpose of the application. These functions should be then be assigned a small set of permissions to perform their necessary operations. Additionally, functions may depend on multiple third-party libraries. When a function is designed in a granular way, these dependencies can be kept at a minimum. Granular functions can also reduce security vulnerabilities in the code.
Secure API Gateway
A Lambda function can be directly exposed to the outside world to be invoked with an HTTP request. However, it is always better to expose the function via Amazon API Gateway.
An API gateway can add an extra layer of security to your functions by implementing additional security features such as request throttling, authentication, and encryption. It should be noted that an API Gateway can work only for HTTP requests. You cannot use it for function invocations from other events such as email, SMS, etc.
Developers are responsible for their API’s security posture when using Lambda and API Gateway. Teams should consider implementing all appropriate authentication and authorization settings with API Gateway. Consider reading the following AWS Documentation for managing access to API Gateway.
Develop Resiliency for Injection Attacks
Injection attacks are one of the oldest types of attack in software applications where an attacker injects malicious code as user inputs. Then, this malicious piece of code can do many harmful things such as extract and send sensitive application data to an outside location. Some developers may get a false sense of security that Lambda functions are not vulnerable to injection attacks because the underlying compute infrastructure is not permanent. This perception is wrong. A Lambda function has access to storages and networks, so is vulnerable to injection attacks similar to any other application running on a VM.
The most common attack surface for injection attacks in a traditional web application would be the HTTP URL parameters, body parameters in POST requests, or HTTP headers. A Web Application Firewall (WAF) can effectively prevent most of these attacks. On the other hand, Lambda functions are event-driven and can be triggered by multiple events from AWS services such as Amazon S3, DynamoDB, Kinesis, API Gateway, and a lot more. A WAF can protect against malicious HTTP requests, but is ineffective at protecting against cloud service execution. Teams should be sure to limit access to Lambda connected cloud resources and ensure that permissions are locked down across these other services.
The first defense against injection attacks for Lambda functions would be to reduce the attack surface by using the concept of least privileges we discussed above. Teams should also consider implementing input sanitization for crucial defense against injection attacks. Even the basic sanitization techniques such as validation of input length and pattern, and elimination of unwanted characters can go a long way in securing your application by making it harder for the attackers to inject malicious code.
Continuously Monitor Your Application
The best practices described so far can enhance the security of your serverless applications by eliminating weaknesses and reducing your overall attack surface. These standards can make it harder for the attackers to exploit your application, but your team can never be sure all possible threats are eliminated.
That’s why cloud and application monitoring is an important aspect of security. Monitoring can provide you with insights about what’s going on with your application. It can help you identify potential security vulnerabilities before they can be exploited. If a vulnerability gets exploited and an attack materializes, monitoring can help you to quickly detect and take appropriate corrective actions to reduce the impact. Dash ComplyOps can help teams continuously monitor security and configuration of Lambda applications and cloud resources across their AWS environments.
In addition to cloud security monitoring, Lambda can be connected to AWS CloudWatch for application and performance monitoring. It can provide you with statistics related to function invocations, duration, and failures, etc. Lambda can also monitor performance metrics such as CPU time, memory, disk, and network usage. Most attacks create anomalies on these metrics. As an example, a sudden increase in network bandwidth could be caused by an attack on your application.
Lambda can also send logs to CloudWatch Logs about the requests handled by your functions. Additionally, you could generate logs within your function and send those logs to CloudWatch Logs. Logs can help you in root cause analysis in the event of an attack, or any other problem in your application. Excessive logging can create a negative impact on performance. Your team should make sure that your functions generate sufficient logs to identify security threats.
AWS Lambda Security Best Practices
While developing a secure serverless architecture may seem daunting, teams should be able to address security concern.
DevOps and Security Team members may consider the following best practices for AWS Lambda when building functions and designing serverless applications:
- Utilize only one IAM Role per Lambda function.
- Do not store AWS Credentials in Lambda function code or configuration.
- Store secrets in EC2 Systems Manager Parameter Store or Lambda Environment Variables with Encryption Helpers.
- Set API authorization and configuration settings when using API Gateway.
- Apply ‘least privilege’ to VPCs related to functions – using function-specific subnets, network ACLs.
- Set access control standards and limit access to Lambda APIs and deployment process.
- Monitor Lambda availability and performance with CloudWatch.
- Ensure security settings for cloud resources connected to Lambda functions (Consider a tool such as Dash ComplyOps).
- Set the most-restrictive permissions possible when setting IAM policies.
- Delete Lambda functions that are no longer in use.
While Amazon Lambda can help reduce application development time and simplify operational activities, your team should not overlook the security configuration and planning required to build secure cloud applications.
Lambda applications are not inherently secure. You must implement the required security in your application code, as well as connected cloud services. In this article, we have discussed best practices that will help you write secure Lambda functions. By implementing all necessary security settings alongside continuous compliance monitoring, your team should be able to ensure uninterrupted, secure applications built on AWS Lambda.
Dash ComplyOps helps teams to ensure security and compliance across AWS environments. Learn how teams manage their AWS security programs with Dash Continuous Compliance Monitoring.